美文网首页
新2019计划:python学习-类【6】

新2019计划:python学习-类【6】

作者: 克里斯托弗的梦想 | 来源:发表于2019-02-21 00:09 被阅读0次

    本篇章,主要介绍类,如何编写类,如何使用属性在类中存储信息,如何编写类的方法,如何修改实例的属性(直接修改和通过方法修改),子类如何继承父类,如何调用类等,以及类在模块中如何调用。

    面向对象编程是最有效的软件编写方法之一。在面向对象编程中,编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。根据类来创建对象被称为实例化。

    • 创建和使用类
      下面来编写一个表示小狗的简单类Dog,它表示的不是特 定的小狗,而是任何小狗。对于大多数宠物狗,我们都知道些什么呢?它们都有名字和年龄;我 们还知道,大多数小狗还会蹲下和打滚。由于大多数小狗都具备上述两项信息(名字和年龄)和 两种行为(蹲下和打滚),我们的Dog类将包含它们。编写这个类后,我们将使用它来创建表示特定小狗的实例。

    创建Dog类
    dog.py


    class Dog():
        def __init__(self, name, age):
            """初始化属性name和age"""
            self.name = name
            self.age = age
        def sit(self):
            """模拟小狗被命令时蹲下"""
            print(self.name.title() + " is now sitting.")
        def roll_over(self):
            """ 模拟小狗被命令时打滚"""
            print(self.name.title() + " rolled over!")
        def add_age(self, number):
            self.age += number
    

    方法init():
    方法init()是一个特殊的方法,每当你根据Dog类创建新实 例时,Python都会自动运行它。
    以self为前缀的变量都可供类中的所有方法使用,我们 还可以通过类的任何实例来访问这些变量。self.name = name获取存储在形参name中的值,并将 其存储到变量name中,然后该变量被关联到当前创建的实例。self.age = age的作用与此类似。像这样可通过实例访问的变量称为属性。

    创建实例

    my_dog = Dog('willie', 6)
    print("My dog's name is " + my_dog.name.title() + ".")
    print("My dog is " + str(my_dog.age) + " years old.")
    # 调用属性
    my_dog.name
    # 调用方法
    my_dog.sit()
    # 修改属性的值
    # 1、直接修改
    my_dog.name = 'volid'
    # 2、方法修改属性的值
    my_dog.add_age(2)
    
    • 继承
      一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类, 而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

    下面来模拟电动汽车。电动汽车是一种特殊的汽车,因此我们可以在前面创建的Car 类的基础上创建新类ElectricCar,这样我们就只需为电动汽车特有的属性和行为编写代码。

    class Car():
        """一次模拟汽车的简单尝试"""
        def __init__(self, make, model, year):
            self.make = make
            self.model = model
            self.year = year
            self.odometer_reading = 0
        def get_descriptive_name(self):
            long_name = str(self.year) + ' ' + self.make + ' ' + self.model 
            return  long_name.title()
        def read_odometer(self):
            print("This car has " + str(self.odometer_reading) + " miles on it.")
    
        def update_odometer(self, mileage):
            if mileage >= self.odometer_reading:
                self.odometer_reading = mileage 
            else:
                print("You can't roll back an odometer!")
        def increment_odometer(self, miles): 
             self.odometer_reading += miles
    
    class ElectricCar(Car):
        def __init__(self, make, model, year):
            """初始化父类的属性"""
                super().__init__(make, model, year)
    
    my_tesla = ElectricCar('tesla', 'model s', 2016)
    print(my_tesla.get_descriptive_name())
    

    super()是一个特殊函数,帮助Python将父类和子类关联起来。这行代码让Python调用 ElectricCar的父类的方法init(),让ElectricCar实例包含父类的所有属性。父类也称为超 类(superclass),名称super因此而得名

    给子类定义属性和方法

    class ElectricCar(Car):
        def __init__(self, make, model, year):
            """初始化父类的属性"""
                super().__init__(make, model, year)
                self.battery_size = 70
    
        def describe_barrery(self):
            """打印一条描述电瓶容量的消息"""
            print("This car has a " + str(self.battery_size) + "-kWh battery.")
    
    my_tesla = ElectricCar('tesla', 'model s', 2016) print(my_tesla.get_descriptive_name()) 
    my_tesla.describe_battery()
    

    添加了新属性self.battery_size,并设置其初始值。还添加了一个名为describe_battery()的方法,它打印有关电瓶的信息。我们调用这个方法时,将看到一条电动汽车特有的描述。

    重写父类方法
    对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子 类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方 法,而只关注你在子类中定义的相应方法。
    假设Car类有一个名为fill_gas_tank()的方法,它对全电动汽车来说毫无意义,因此你可能 想重写它。下面演示了一种重写方式:

    def ElectricCar(Car):
        --snip--
        def fill_gas_tank():
            """电动汽车没有油箱"""
            print("This car doesn't need a gas tank!")
    

    如果有人对电动汽车调用方法fill_gas_tank(),Python将忽略Car类中的方法 fill_gas_tank(),转而运行上述代码。使用继承时,可让子类保留从父类那里继承而来的精华, 并剔除不需要的糟粕。

    将实例用作属性
    使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多:属性和方法清单以及文 件都越来越长。在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。你可以将大 型类拆分成多个协同工作的小类。
    不断给ElectricCar类添加细节时,我们可能会发现其中包含很多专门针对汽车电瓶 的属性和方法。在这种情况下,我们可将这些属性和方法提取出来,放到另一个名为Battery的 类中,并将一个Battery实例用作ElectricCar类的一个属性。

    class Car():
        -- snip --
    
    class Battery():
        """一次模拟电动汽车电瓶的简单尝试"""
        def __init__(self, battery_size=70):
            """初始化电瓶的属性"""
            self.battery_size = battery_size
        def describe_battery(self):
            """打印一条描述电瓶容量的消息"""
            print("This car has a " + str(self.battery_size) + "-kWh battery.")
    
    class ElctricCar(Car):
        """电动汽车的独特之处"""
        def __init__(self, make, model, year):
            """初始化父类的属性,再初始化电动汽车特有的属性"""
            super().__init__(make, model, year)
            self.battery = Battery()
    
    my_tesla = ElectricCar('tesla', 'model s', 2016)
    print(my_tesla.get_descriptive_name())
    my_tesla.battery.describe_battery()
    
    • 导入类
      car.py

    class Car():
        """一次模拟汽车的简单尝试"""
        def __init__(self, make, model, year): 
            """初始化描述汽车的属性""" 
            self.make = make
            self.model = model
            self.year = year self.odometer_reading = 0
        def get_descriptive_name(self):
            """返回整洁的描述性名称"""
            long_name = str(self.year) + ' ' + self.make + ' ' + self.model 
            return long_name.title()
        def read_odometer(self):
            """打印一条消息,指出汽车的里程"""
            print("This car has " + str(self.odometer_reading) + " miles on it.")
        def update_odometer(self, mileage): 
            """
            将里程表读数设置为指定的值 拒绝将里程表往回拨
            """
            if mileage >= self.odometer_reading:
                self.odometer_reading = mileage else:
                print("You can't roll back an odometer!")
        def increment_odometer(self, miles): 
            """将里程表读数增加指定的量""" 
            self.odometer_reading += miles
    

    my_car.py


    from car import car
    my_new_car = Car('audi', 'a4', 2016)
    print(my_new_car.get_descriptive_name())
    my_new_car.odometer_reading = 23
    

    同样,一个模块也可以写入多个类,如果从一个模块中导入多个类,例如:
    from car import Car, ElectricCar ,导入整个模块,例如:import car。导入模块中所有类:from module_name import *。还可以在一个模块中导入另一个模块,也就是说一个模块A导入了另一个模块B,然后模块C导入模块A,那么B模块也其实导入了。

    • 类编码风格
      你必须熟悉有些与类相关的编码风格问题,在你编写的程序较复杂时尤其如此。类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名 和模块名都采用小写格式,并在单词之间加上下划线。对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的 功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串, 对其中的类可用于做什么进行描述。可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import语句,再 添加一个空行,然后编写导入你自己编写的模块的import语句。在包含多条import语句的程序中, 这种做法让人更容易明白程序使用的各个模块都来自何方。

    相关文章

      网友评论

          本文标题:新2019计划:python学习-类【6】

          本文链接:https://www.haomeiwen.com/subject/yexlyqtx.html