第九章 类
1. 创建和使用类
class Dog(): # 创建名为Dog的类,类名一般首字母大写
"""一次模拟小狗的简单尝试""" # 文档字符串
def __init__(self, name, age): # 方法__init__()
""" 初始化属性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__( )
是一种特殊的方法,每当根据类创建新实例时,Python都会自动运行这个方法。在这个方法的定义中,形参 self 必不可少,还必须位于其他形参的前面,因为Python调用这个__init__() 方法来创建实例时,将自动传入实参self 。每个与类相关联的方法调用都自动传递实参self ,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
根据类创建实例
class Dog(): # 创建名为Dog的类,类名一般首字母大写
--snip--
my_dog = Dog('willie', 6) # 创建实例并存储在变量my_dog
中
print("My dog's name is " + my_dog.name.title() + ".") # 访问实例属性
my_dog.sit() # 调用方法
her_dog = = Dog('lucy',3) # 创建多个实例
- 访问属性
使用句点表示法访问实例的属性,my_dog.name - 调用方法
使用句点表示法调用类中的方法,my_dog.sit() - 创建多个实例
可以根据一个类创建任意数量的实例,条件是将每个实例都存储在不同的变量中,或占用列表或字典的不同位置。
2. 使用类和实例
class Car():
def __init__(self, make, model, year):
self.make = make # 使用形参给属性指定默认值
self.model = model
self.year = year
self.odometer_reading = 0 # 直接指定初始值
def read_odometer(self): "
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self, mileage):
self.odometer_reading = mile
def increment_odometer(self, miles): """ 将里程表读数增加指定的量"""
self.odometer_reading += miles
my_new_car = Car('audi', 'a4', 2016)
my_new_car.read_odometer() # 获取属性的值
my_new_car.odometer_reading = 23 # 直接通过实例修改属性的值
my_new_car.update_odometer(23) # 通过方法修改属性的值;
my_used_car.increment_odometer() # 通过方法对属性的值进行递增
给属性指定默认值
可以使用形参给实例属性指定默认值,也可以在__init__()方法中直接给属性指定默认值。
修改属性的值
- 直接通过实例修改属性的值;
- 通过方法修改属性的值;
- 通过方法对属性的值进行递增。
3. 继承
一个类 继承 另一个类时,它将自动获得另一个类的所有属性和方法;原有的 类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。
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 increment_odometer(self, miles):
self.odometer_reading += miles
class CarSize():
def __init__(self, car_size='small'):
self.car_size = car_size
def describe_car(self):
print("This car is " + self.car_size)
class ElectricCar(Car): # 创建子类
def __init__(self, make, model, year):
super().__init__(make, model, year) # 初始化父类的属性
self.battery_size = 70 # 定义子类的属性
self.size = CarSize() # 将实例用作属性
def describe_battery(self): # 定义子类的方法
print("This car has a " + str(self.battery_size) + "-kWh battery.")
def read_odometer(self): # 重写父类的方法
print("This new car has " + str(self.odometer_reading) + " miles on it.")
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.size.describe_car()
创建子类时,父类必须包含在当前文件中,且位于子类前面。
定义子类时,必须在括号内指定父类的名称。
子类的方法 init()
创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值。
super() 函数将父类和子类关联起来。
给子类定义属性和方法
与之前定义属性和方法一致。
重写父类的方法
可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样, Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法行为。
将实例用作属性
使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多,属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。 你可以将大型类拆分成多个协同工作的小类。
self.size = CarSize() # 将实例用作属性。每当 ElectricCar类中国方法__init__() 被调用时,都将执行该操作,因此现在每个ElectricCar 实例都包含一个自动创建的CarSize实例。
4. 导入类
Python允许将类存储在模块中,然后在主程序中导入所需的模。
在一个模块中存储多个类
尽量将多个存在相关性的类存储在同一个模块中。
导入单个类、多个类、整个模块
from car import Car # 导入单个类
# 其中 car 是模块(.py 文件名),Car为其中的类名。
from car import Car, ElectricCar # 导入多个类
import car # 导入整个模块
car.Car() # 使用句点表示法访问需要的类
from car import * # 导入模块中的所有类
# 不推荐这种方法,没有明确指出具体应用了哪些类,易引发名称方面的困惑。
5. 类编码风格
- 类名应采用驼峰命名法 驼峰命名法 ,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
- 对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
- 可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
- 需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的 import 语句,再添加一个空行,然后编写导入你自己编写的模块的 import 语句。