Knowledge Supplement 3: Python - Inheritance of Classes

class base

class Dog:
    # 从空白中创建这个类,所以定义中没有圆括号
    # 类的首字母要大写
    def __init__(self, name, age):
        # init两边各两个下划线,这是一种特殊方法
        # 这个方法定义成包含三个形参(首位必须有且为self)
        # 根据Dog类创建新实例时,这个方法会自动调用,并自动传入实参self
        # 只需给后面的形参(name和age)提供值
        # 每个与实例相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法
        self.name = name
        self.age = age
        # 以self为前缀的变量可供类中所有方法使用
        # 还可以通过类的任何实例来访问(这类的变量称为属性)

    def sit(self):
        # 这个方法不需要额外的信息,所以只有一个形参self
        print(f"{self.name} is now sitting.")

    def roll_over(self):
        print(f'{self.name} rolled over!')


jack = Dog('Jack', 18)
# 创建实例
jack.name
# 访问属性
jack.sit()
jack.roll_over()
# 调用方法

class properties 

class User:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.age = 18
        # 指定默认属性值

    def describe_user(self):
        print(self.first_name, self.last_name)

    def greet_user(self):
        print(f'Hello, {self.first_name} {self.last_name}')

    def update_age_1(self, age):
        if age >= self.age:
            self.age = age
        else:
            print('新设置的年龄不能比之前的小')

    def update_age_2(self, age):
        self.age += age

    def update_age_3(self):
        self.age += 1


myself = User('Hugo', 'Ho')
myself.describe_user()
myself.greet_user()
print(myself.age)
myself.age = 20
print(myself.age)
# 直接修改属性的值
myself.update_age_1(29)
print(myself.age)
# 通过方法修改属性的值
myself.update_age_2(11)
print(myself.age)
# 通过方法对属性的值进行递增(自定义值)
myself.update_age_3()
print(myself.age)
# 通过方法对属性的值进行递增(固定值)

class inheritance

When writing a class, you can start from scratch, or you can use inheritance (a new class is a special version of an existing class).

  • When a class inherits another class, it will automatically get all the properties and methods of the other class (you can also define your own properties and methods).
  • The original class is called the parent class, and the newly created class is called the subclass.

Subclass method __init__()

When writing a subclass based on the parent class, the method __init__() of the parent class is usually called. This will initialize all attributes defined in the superclass's __init__() method, thus allowing subclasses to include them.

In the following code, the subclass ElectricCar is written on the basis of the parent class Car, so that the latter has all the functions of the former:

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 = f'{self.year} {self.make} {self.model}'
        return long_name.title()

    def read_odometer(self):
        """打印一条汽车里程信息"""
        print(f'This car has {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):
    # 方法__init__()接收创建Car实例所需的信息
        """初始化父类的属性"""
        super().__init__(make, model, year)
        # super()是一个特殊函数,可以实现对父类方法的调用
        # 这里super()函数调用了Car类的方法__init__(),让ElectricCar实例包含这个方法中定义的所有属性
        # 父类也称为超类(superclass),名称super由此而来


my_tesla = ElectricCar('tesla', 'model s', 2019)
# 创建一个ElectricCar实例,并将其赋给变量my_tesla
# 这行代码会自动调用子类ElectricCar中定义的方法__init__(),后者会让Python调用父类Car中定义的方法__init__()
print(my_tesla.get_descriptive_name())

output:

2019 Tesla Model S

Define properties and methods for subclasses

After the subclass inherits the parent class, you can add new attributes and new methods needed to distinguish it from the parent class.

class Car:
    --snip--

class ElectricCar(Car):
    """电动汽车的独特之处。"""

    def __init__(self, make, model, year):
        """
        初始化父类的属性。
        初始化子类特有的属性。
        """
        super().__init__(make, model, year)
        self.battery_size = 75
        # 添加子类的新属性(根据ElectricCar类创建的实例都包含该属性,其他Car类的实例不包含)

    def describe_battery(self):
    # 添加子类的新方法
        """打印一条描述电池容量的消息。"""
        print(f"This car has a {self.battery_size}-kWh battery.")


my_tesla = ElectricCar('tesla', 'model s', 2019)
# 创建一个ElectricCar的实例
print(my_tesla.get_descriptive_name())
# 调用子类从父类继承过来的方法
my_tesla.describe_battery()
# 调用子类自己定义的方法

output:

2019 Tesla Model S
This car has a 75-kWh battery.

Overriding the method of the parent class

You can define a method in the subclass with the same name as the superclass method to be overridden.

class Car:
    --snip--

class ElectricCar(Car):
    """电动汽车的独特之处。"""

    def __init__(self, make, model, year):
        """
        初始化父类的属性。
        初始化子类特有的属性。
        """
        super().__init__(make, model, year)
        self.battery_size = 75

    def describe_battery(self):
        """打印一条描述电池容量的消息。"""
        print(f"This car has a {self.battery_size}-kWh battery.")

    def get_descriptive_name(self):
        """返回完整的描述性信息(带新能源标识)。"""
        long_name = f'[新能源] {self.year} {self.make} {self.model}'
        # 重写父类中的同名方法并加上“[新能源]”标识
        return long_name.title()


my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
# 此时Python不再考虑父类方法,而只关注子类中定义的相应方法
my_tesla.describe_battery()

[New Energy] 2019 Tesla Model S
This car has a 75-kWh battery.

use instance as attribute

Part of a class can be extracted as an independent class (split a large class into multiple small classes that work together).

The following extracts some properties and methods of ElectricCar, put them into a class named Battery, and use a Battery instance as the property of the ElectricCar class.

class Car:
    --snip--

class ElectricCar(Car):
    """电动汽车的独特之处。"""

    def __init__(self, make, model, year):
        """
        初始化父类的属性。
        初始化子类特有的属性。
        """
        super().__init__(make, model, year)
        self.battery = Battery()
        # 添加新属性,连接Battery类(创建一个Battery类的实例,每当方法__init__被调用时,都将执行该操作)
        # 现在每个ElectricCar实例都包含一个自动创建的Battery实例

    def get_descriptive_name(self):
        """返回完整的描述性信息(带新能源标识)。"""
        long_name = f'[新能源] {self.year} {self.make} {self.model}'
        return long_name.title()


class Battery:
# 定义一个名为Battery的新类(没有继承任何类)
    """电动车电池的相关属性和方法。"""

    def __init__(self, battery_size=75):
    # 加入形参battery_size,如果没有提供值,电池容量默认就是75
        """初始化电瓶的属性"""
        self.battery_size = battery_size

    def describe_battery(self):
        """打印一条描述电池容量的消息。"""
        print(f"This car has a {self.battery_size}-kWh battery.")


my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
# 描述电瓶的时候,需要使用ElectricCar类的属性battery

output: 

[New Energy] 2019 Tesla Model S
This car has a 75-kWh battery.

Modify the value of an instance (property) of an instance (class)

class Car:
    --snip--

class ElectricCar(Car):
    --snip--

class Battery:
    --snip--

my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.battery.battery_size = 100
# 通过修改ElectricCar的实例(my_tesla)中的属性(battery)中的属性(battery_size)的值
my_tesla.battery = Battery(100)
# 通过修改ElectricCar的实例(my_tesla)中的属性(battery)对应的实例(Battery)的参数值
my_tesla.battery.describe_battery()

output:

[New Energy] 2019 Tesla Model S
This car has a 100-kWh battery.

 A car is composed of many modules. If you want to describe each module in detail, it is best to arrange different modules in different classes, and then insert these classes into a summary in the form of instances. In the properties of the class, just call it when needed.

Let's add another method to the Battery class that will report the car's range based on the battery capacity.

class Car:
    --snip--

class ElectricCar(Car):
    --snip--

class Battery:
    """电动车电池的相关属性和方法。"""

    def __init__(self, battery_size=75):
        """初始化电瓶的属性"""
        self.battery_size = battery_size

    def describe_battery(self):
        """打印一条描述电池容量的消息。"""
        print(f"This car has a {self.battery_size}-kWh battery.")

    def get_nedc(self):
    # 新增方法作简单的分析,根据电池容量报告续航里程
        """打印一条消息,描述电瓶的续航里程"""
        if self.battery_size == 75:
            nedc = 260
        elif self.battery_size == 100:
            nedc = 315
        print(f"This car can go about {nedc} miles on a full charge.")


my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
# my_tesla.battery.battery_size = 100
my_tesla.battery.describe_battery()
my_tesla.battery.get_nedc()
# 通过调用实例的属性的方法来获取信息

output:

[新能源] 2019 Tesla Model S
This car has a 75-kWh battery.
This car can go about 260 miles on a full charge.

class import

Import multiple classes from a module

from car import Car, ElectricCar


my_beetle = Car('volkswagen', 'beetle', 2019)

my_tesla = Car('tesla', 'roadster', 2019)

import the whole module

import Car

my_beetle = car.Car('volkswagen', 'beetle', 2019)

my_tesla = car.ElectricCar('tesla', 'roadster', 2019)

import all classes in the module

from car import *
# 不推荐使用
# 不能一目了然清楚使用了模块里面的哪些类
# 引发名称方面的迷惑(如果出现同名的类会产生错误)
# 推荐使用导入整个模块,然后用“模块名.类名”的语法来访问类

Import the class and specify the alias

from electric_car import ElectricCar as EC

my_tesla = EC('tesla', 'roadster', 2019)

class coding style

  • The class name adopts the camel case naming method: the first letter of each word is capitalized, no underscore is used (instance names and module names are in lower case format, and underscores are added between words)
  • The end of the class definition and the beginning of the module are followed by a docstring that briefly describes the function of the class
  • In a module, there are two blank lines between two classes. In a class, there is a blank line between two methods.
  • First import the modules of the standard library and then import the modules written by yourself

<end>

Guess you like

Origin blog.csdn.net/weixin_58695100/article/details/122716658