8.类--《Python编程:从入门到实践》
8.1 创建类
根据约定,在Python中,首字母大写的名称指的是类。 这个类定义中的括号是空的,因为我们要从空白创建这个类。在Python 2.7中创建类时,需要做细微的修改——在括号内包含单词object。
(1) _init 方法
这里将方法__init__()定义成了包含三个形参:self、name和age。在 init 的定义中,形参 self 必不可少,还必须位于其他形参的前面。self 是指向实例本身的引用,让实例能够访问类中的属性和方法。
我们将通过实参向Dog()传递名字和年龄;self 会自动传递,因此我们不需要传递它。每当我们根据Dog类创建实例时,都只需给最后两个形参(name和age)提供值。
(2) 属性
以self为前缀的变量都可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。这样通过实例访问的变量称为属性。如 self.name。
class Dog(object):
"""一次模拟小狗的简单尝试"""
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!")
d = Dog("W","18")
d.sit()
print(d.name,"is",d.age,"years old" )
8.1.1 属性的默认值
类中的每个属性都必须有初始值。在有些情况下,如设置默认值时,在方法__init__()内指定这种初始值是可行的;如果你对某个属性这样做了,就无需包含为它提供初始值的形参。当然我们修改这个属性的值时,可以建立一个方法来修改。
class Car():
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0 # 设置默认值,PS:无需包含为它提供初始值的形参
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):
"""将里程表读数设置为指定的值"""
self.odometer_reading = mileage
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
my_new_car.update_odometer(20) # 更新表示里程的属性,她之前是个默认值
my_new_car.read_odometer()
8.2 继承
我们来创建一个电动汽车 ElectricCar 的类,继承于上面所写的汽车 Car 这个父类。创建子类时,父类必须包含在当前文件中,且位于子类前面,子类必须在括号内指定父类的名称。
给子类定义属性和方法:让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。这里添加一个关于电瓶容量的属性和方法。
重写父类的方法:对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。假设Car类有一个名为fill_gas_tank()的方法,因为电动汽车没有油箱,我们要进行改写。
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""
电动汽车的独特之处
初始化父类的属性,再初始化电动汽车特有的属性
"""
super().__init__(make, model, year)
self.battery_size = 70 # 子类特有的成员属性
# 子类特有的成员函数
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print("This car has a " + str(self.battery_size) + "-kWh battery.")
# 重写父类的方法
def fill_gas_tank(self):
"""电动汽车没有油箱"""
print("This car doesn't need a gas tank!")
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
my_tesla.fill_gas_tank()
8.3 导入类
类似导入函数。
from car import Car # 从 car.py 导入 Car 类
import car # 导入整个 car.py
8.4 类的编码风格
类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。
每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import语句,再添加一个空行,然后编写导入你自己编写的模块的import语句。