类(class)简介

1 引言

在面向对象编程中,编写表示现实世界中的事物和情景的类,并基于这些类来创建对象(实例化),使每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性,使用面向对象编程可模拟现实情景。

2 创建和使用类

使用类几乎可以模拟任何东西,如创建一个表示小狗的简单类Dog,由于大多数小狗都有名字和年龄,都会蹲下和打滚,故Dog类可以包含这些信息和行为,成为一个表示小狗的对象,进而可以使用它来创建表示特定小狗的实例。

2.1 创建Dog类

根据Dog类创建的每个实例都将存储名字和年龄,并赋予每条小狗蹲下(sit( ))和打滚(roll_over( ))的能力:

根据约定,在Python中,首字母大写的名称指的是类。

方法__init__( )

类中的函数称为方法,有关函数的一切都适用于方法,唯一重要差别是调用方法的方式。每当你根据Dog类创建新实例时,Python都会自动运行它。

方法__init__( )定义包含了三个形参:self、name和age。其中形参self必不可少,还必须位于其他形参前面。

2.2 根据类创建实例

可将类视为有关如何创建实例的说明。Dog类是一系列说明,让Python知道如何创建表示特定小狗的实例。

2.2.1 访问属性

my_dog.name

my_dog.age

2.2.2 调用方法

my_dog.sit( )

my_dog.roll_over( )

2.2.3 创建多个实例

创建了名为Willie和Lucy的两条小狗实例。即使给第二条小狗指定相同的名字和年龄,Python依然会根据Dog类创建另一个实例。

3 使用类和实例

3.1 创建一个汽车类

创建一个表示汽车的类,存储有关汽车相关的信息,还包含一个汇总这些信息的方法:

3.2 给属性指定默认值

类中的每个属性都必须有初始值,在方法__init__( )内指定初始默认值是被允许的。如果你对某个属性指定了默认值,就无需包含为它提供初始值的形参。

如添加一个odometer_reading的属性,初始值设为0。为此,还添加一个名为read_odometer( )的方法,用于读取汽车的里程表。

3.3 修改属性的值

有三种不同方式修改属性的值,如下所示:

3.3.1 直接修改属性的值

修改属性的值,最简单的方式是通过实例直接访问它。

3.3.2 通过方法进行设置

无需访问属性,将值传递给一个方法,由它在内部进行更新。

例如,创建一个名为update_odometer( )方法,如下所示:

还可对update_odometer( )方法进行扩展,添加逻辑用于禁止任何人将里程表读数往回调:

3.3.3 通过方法进行递增(增加特定的值)

4 继承

编写类时,并非总是要从空白开始。如果你要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法。原有的类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

4.1 子类的方法__init__( )

创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值。为此,子类的方法__init__( )需要给父类施以援手。

创建一个简单的ElectronicCar类版本,它具备Car类的所有功能:

创建子类时,父类必须包含在当前文件中,且位于子类前面。定义子类时,必须在括号内指定父类的名称。方法__init__( )接受创建Car实例所需的信息。super( )是一个特殊函数,帮助Python将父类和子类关联起来。如雷也称超类,名称super因此得名。

为测试继承是否能够正确地发挥作用,可以创建一辆电动汽车,但提供信息与创建普通汽车时相同,将其存储在变量my_tesla中,如下所示:

4.2 给子类定义属性和方法

让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。

这里我们来添加一个电动汽车特有的属性(电瓶),以及一个描述该属性的方法。

存储电瓶容量,并编写一个打印电瓶描述的方法:

添加新属性电瓶容量并设置初始值为70,根据ElectricCar类创建的所有实例都将包含这个属性,但所有Car实例都不包含它。

此外,还添加了一个名为describe_battery( )的方法,它打印有关电瓶的信息。当调用此方法时,将看到一条电动汽车特有的描述:

4.3 重写父类的方法

对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

例如,Car类有一个名为fill_gas_tank( )的方法,它对全电动汽车来说毫无意义,因此你可能想重写它,如下所示:

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

4.4 将实例用作属性

当给类添加的细节越来越多:属性和方法清单以及文件都越来越长。这种情况下,可能需要将类的一部分作为一个独立的类提取出来,即将大型的类拆分成多个协同工作的小类。

如上所示,添加一个名为Battery的新类,它没有继承任何类。其方法__init__( )除self外,还有另一个形参battery_size。这个形参是可选的:如果没有给它提供值,电瓶容量将被设置为70。

在ElectricCar类中,添加了一个名为self.battery的属性,这行代码让Python创建一个新的Battery实例,并存储在属性self.battery中。每当方法__init__( )被调用时,都将执行该操作,因此现在每个ElectricCar实例都包含一个自动创建的Battery实例。

5 导入类

为了方便使用定义的各种类,一般将类存储在模块中,然后在主程序中导入所需的模块。

5.1 导入单个类

创建一个car.py模块并将Car类包含在里面,如下所示:

接着创建另一个my_car.py文件,在其中导入Car类并创建其实例:

此为导入类的一种方式,通过将类移到一个模块中,并导入该模块,便可使用类的所有功能,同时,主程序文件变得整洁而易于阅读。

5.2 在一个模块中存储多个类

Python中,用户在一个模块中存储任意数量的类是被允许的,如下所示:

接着创建一个名为my_electric_car.py的文件,导入ElectricCar类,并创建一辆电动汽车:

5.3 其他导入类方式

1. 从一个模块中导入多个类

2. 导入整个模块

3. 导入模块中的所有类

猜你喜欢

转载自www.cnblogs.com/yangmi511/p/12403579.html
今日推荐