《Python编程:从入门到实践》 第 9 章 类

第 9 章 类

这里简单阐述了什么是“面向对象编程”,以及“对象”、“实例化”的概念,与面向对象在编程中的重要性。

9.1 创建和使用类

在这里编写个小狗类,这个 Dog 类里面有小狗的名字和年龄信息与蹲下和打滚两项行为。

9.1.1 创建 Dog 类

用 Dog 类创建的每个实例都将储存名字和年龄,和它的两项行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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!")

根据约定,在Python中,首字母大写的名称指的是类。这个类定义中的括号是空的,因为我们要从空白创建这个类。

  1. 方法 __init__()

    类中的函数称为方法__init__() 是一个特殊的方法,每当创建新实例时,Python 会自动运行它。它前后个有两个下划线,这是为了避免 Python 默认方法与普通方法名称冲突。__init__() 方法必须有个 self 形参,并且是形参中的第一个。 当创建类实例时会自动传入。

    注:我的理解是先给实例创建了地址,把这个地址作为 self 传入到 __init__() 方法中。

  2. 在 Python 2.7 中创建类

    在 Python 2.7 中略有差异。需要在类名后的括号中当单词 object。在 Python 2.7 中定义 Dog 类时,代码类似于下面这样:

    1
    2
    class Dog(object):
    --snip--

9.1.2 根据类创建实例

9.3 继承

说了下什么是继承、父类、子类,继承的一些基本特性。

9.3.1 子类的方法 __init__()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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())

创建子类时,父类必须包含在当前文件中,且位于子类前面。
定义子类时,必须在括号内指定父类的名称。
方法__init__() 接受创建Car 实例所需的信息。

9.4 导入类

为遵循 Python 的总体理念,应让文件尽可能整洁。Python 允许将类储存在模块中,然后在主程序中导入需要的模块。

9.4.1 导入单个类

car.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
"""一个可用于表示汽车的类"""

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

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

car.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

"""一组用于表示燃油汽车和电动汽车的类"""

class Car():
--snip--


class Battery():
"""一次模拟电动汽车电瓶的简单尝试"""

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

--snip--

class ElectricCar(Car):
"""模拟电动汽车的独特之处"""
def __init__(self, make, model, year):
"""
初始化父类的属性,再初始化电动汽车特有的属性
"""
super().__init__(make, model, year)
self.battery = Battery()

9.4.3 从一个模块中导入多个类

my_cars.py

1
2
3
4
5
6
7
from car import Car, ElectricCar

my_beetle = Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())

my_tesla = ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())

9.4.4 导入整个模块

my_cars.py

1
2
3
4
5
6
7
import car

my_beetle = car.Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())

my_tesla = car.ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())

9.4.5 导入模块中的所有类

1
from module_name import *

9.4.6 在一个模块中导入另一个模块

electric_car.py

1
2
3
4
5
6
7
8
9
"""一组可用于表示电动汽车的类"""

from car import Car

class Battery():
--snip--

class ElectricCar(Car):
--snip--

9.4.7 自定义工作流程

9.5 Python 标准库

Python 标准库是一组模块,安装的 Python 都包含它。OrderedDict 类为标准库 collections 模块中的一个类。它和字典就有相同的功能,同时保留添加的顺序。

1
2
3
from collections import OrderedDict

favorite_languages = OrderedDict()

这里没有使用花括号,而是调用 OrderedDict() 来创建一个空的有序字典,并将其存储在favorite_languages 中。

9.6 类编码风格

命名规范:

  • 类名应采用驼峰命名法
  • 实例名和模块名都采用小写格式,单词间用下划线连接。

文档字符串:

  • 每个类都应包含一个文档字符串;
  • 每个模块都应包含一个文档字符串。

用空行组织代码:

  • 在类中,可使用一个空行来分隔方法;
  • 而在模块中,可使用两个空行来分隔类。

导入模块:

import 标准库后留个空行,再写导入自己编写模块的 import

9.7 小结

知识点:

  • 如何编写类;
  • 如何编写方法 _init__()`;
  • 如何使用属性在类中存信息;
  • 如何编写类的方法;
  • 如何用类创建实例;
  • 如何修改实例属性(直接或通过方法);
  • 如何使用继承;
  • 如何将类放到模块中;
  • 如何导入模块中的类;
  • 如何使用 Python 标准库;
  • 如何使用标准库中的 collections;
  • 编写 Python 类的约定。