创建和使用类

面向对象编程是最有效的软件编写方法之一。在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。编写类时,你定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。
根据约定,在Python中,首字母大写的名称指的是类。

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

方法__init__()

类中的函数称为方法_init_是一个特殊的方法,根据类进行新的实例的创建时,都会自动运行_init_,下划线是约定必须遵循。
形参self必不可少,且必须放在其他形参的前面,是一个指向实例本身的引用,让实例能够访问类中的属性和方法
属性:句号表示法,后面没有括号
方法:句号表示法,后面有括号

根据类创建实例

  1. 访问属性
  2. 调用方法
  3. 创建多个实例
1
2
3
4
my_dog = Dog('willie', 6) 
print(my_dog.name + "\n" + str(my_dog.age))
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")
willie
6
My dog's name is Willie.
My dog is 6 years old.
1
2
3
my_dog = Dog('willie', 6) 
my_dog.sit()
my_dog.roll_over()
Willie is now sitting.
Willie rolled over!
1
2
3
4
my_dog = Dog('willie', 6) 
your_dog = Dog('lucy', 3)
print(my_dog.name)
print(your_dog.name)
willie
lucy

使用类和实例

1
2
3
4
5
6
7
8
9
10
11
12
class Car(): 
"""一次模拟汽车的简单尝试"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year

def get_descriptive_name(self):
"""返回整洁的描述性信息"""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
1
2
my_new_car = Car('audi', 'a4', 2016) 
print(my_new_car.get_descriptive_name())
2016 Audi A4

给属性指定默认值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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.")

my_new_car = Car('audi', 'a4', 2016)
my_new_car.read_odometer()
This car has 0 miles on it.

Python将创建一个名为odometer_reading的属性,并将其初始值设置为0

修改属性的值

  1. 直接修改
  2. 通过方法修改
1
2
3
4
my_new_car = Car('audi', 'a4', 2016) 
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
2016 Audi A4
This car has 23 miles on it.
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
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:
return self.odometer_reading

my_new_car = Car('audi', 'a4', 2016)
my_new_car.update_odometer(666)
my_new_car.update_odometer(66)
my_new_car.read_odometer()
This car has 666 miles on it.

继承

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

重写父类的方法

比如电动车没有油箱,但是电动车的父类有邮箱,那么需要重写父类以符合对模拟的要求,定义一个与要重写的父类方法同名的方法即可

将实例用作属性

将大型类拆分成多个协同工作的小类

1
2
3
4
5
6
7
8
9
class ElectricCar(Car): 
"""电动汽车的独特之处"""

def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year)
# 这行代码让Python调用ElectricCar的父类的方法__init__(),让ElectricCar实例包含父类的所有属性
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
2016 Tesla Model S

super()是一个特殊函数,帮助Python将父类和子类关联起来

1
2
3
4
5
6
7
8
9
10
11
# 重写父类的方法,给get_descriptive_name()方法加上一句话
class Hydrogen_Energy_Automobile(Car):
def __init__(self, make, model, year):
super().__init__(make, model, year)

def get_descriptive_name(self):
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title() + "\nThis car doesn't need a gas tank!"

my_Huawei = Hydrogen_Energy_Automobile('wenjie', 'm9 ', 2023)
print(my_Huawei.get_descriptive_name())
2023 Wenjie M9 
This car doesn't need a gas tank!

将实例用作属性

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
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.")

def get_range(self):
"""打印一条消息,指出电瓶的续航里程"""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270

message = "This car can go approximately " + str(range)
message += " miles on a full charge."
print(message)

class ElectricCar(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()
2016 Tesla Model S
This car has a 70-kWh battery.
1
my_tesla.battery.get_range()
This car can go approximately 240 miles on a full charge.

导入类

和导入函数差不多
Python允许你将类存储在模块(文件)中,然后在主程序中导入所需的模块

  1. 导入单个类
  2. 在一个模块中存储多个类
  3. 从一个模块中导入多个类
  4. 导入整个模块
  5. 导入模块中的所有类 from module_name import *
  6. 在一个模块中导入另一个模块
  7. 自定义工作流程

Python 标准库

字典让你能够将信息关联起来,但它们不记录你添加键—值对的顺序。要创建字典并记录其中的键—值对的添加顺序,可使用模块collections中的OrderedDict类

1
2
3
4
5
6
7
8
9
10
11
from collections import OrderedDict 

favorite_languages = OrderedDict()

favorite_languages['jen'] = 'python'
favorite_languages['sarah'] = 'c'
favorite_languages['edward'] = 'ruby'
favorite_languages['phil'] = 'python'

for name, language in favorite_languages.items():
print(name.title() + "'s favorite language is " + language.title() + ".")
Jen's favorite language is Python.
Sarah's favorite language is C.
Edward's favorite language is Ruby.
Phil's favorite language is Python.
1
2
3
4
5
6
7
# 骰子:模块 random 包含以各种方式生成随机数的函数,其中的 randint()返回
# 一个位于指定范围内的整数,例如,下面的代码返回一个 1~6 内的整数:
# from random import randint
# x = randint(1, 6)
# 请创建一个 Die 类,它包含一个名为 sides 的属性,该属性的默认值为 6。编写一
# 个名为 roll_die()的方法,它打印位于 1 和骰子面数之间的随机数。创建一个 6 面的骰
# 子,再掷 10 次。创建一个 10 面的骰子和一个 20 面的骰子,并将它们都掷 10 次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from random import randint 
# randint()返回一个位于指定范围内的整数

class Die:
def __init__(self, side):
self.side = side

def roll_die(self):
x = randint(1, self.side)
return x

my_die = Die(6)
print("这是一个" + str(my_die.side) + "面的骰子")
print("随机骰出的数字是:" + str(my_die.roll_die()))
这是一个6面的骰子
随机骰出的数字是:3

了解Python标准库
https://pymotw.com/3/

类编码风格

类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线
实例名和模块名都采用小写格式,并在单词之间加上下划线
在每个类后面需要包含一个文档字符串
在类中,可使用一个空行分隔方法;而在模块中,可使用两个空行分隔类