Appearance
类
面向对象编程是最有效的软件编写方法之一。在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。
编写类时,你定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。
根据类来创建对象被称为实例化,这让你能够使用类的实例。
例如 猫 是一个类, 灰灰是一个实例,有自己的属性和行为。
1.创建类 和 实例
1.1 创建类
根据Dog类创建的每个实例都将存储名字和年龄。我们赋予了每条小狗蹲下(sit())和打滚(roll_over())的能力:
类可以有默认值,例如小狗的 sitting 属性默认值为 False。
python
class Dog:
"""一个简单的小狗类"""
def __init__(self, name, age):
"""初始化属性name和age"""
self.name = name
self.age = age
self.sitting = False # 默认值为 False
def sit(self):
"""模拟小狗蹲下"""
print(f"{self.name} is now sitting")
def roll_over(self):
"""模拟小狗打滚"""
print(f"{self.name} is now rolling over")- 1.方法__init__()
- 每个类都必须包含一个名为__init__()的方法,用于初始化创建的实例。
- 开头和末尾各有
两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。 - 在__init__()方法中,定义了创建小狗实例所需的所有属性。
self参数是必不可少的,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
self
[ self ]
自己
1.2 创建实例
根据类创建实例时,每个实例都自动具备这种通用行为,然后可根据需要赋予每个实例独特的个性。
python
# 根据类创建实例
my_dog = Dog("Willie", 6)
# 访问属性
print(f"My dog's name is {my_dog.name}.")
# 调用方法
my_dog.sit()
my_dog.roll_over()2. 修改属性的值
下面来编写一个表示汽车的类,它存储了有关汽车的信息,还有一个汇总这些信息的方法:
python
class Car:
"""一个简单的汽车类"""
def __init__(self, make, model, year):
"""初始化汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0 # 里程 默认值为 0
def get_descriptive_name(self):
"""返回整洁的描述性信息"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
my_car = Car("audi", "a4", 2019)
print(my_car.get_descriptive_name())2.1.直接修改属性的值
直接访问并设置属性的值
python
my_car.odometer_reading = 23
print(f"My car has {my_car.odometer_reading} miles on it.")2.2.通过方法修改属性的值
python
class Car:
--上面代码不变,下面增加--
def update_odometer(self, mileage):
"""将里程表读数设置为指定的值"""
self.odometer_reading = mileage
# 使用方法修改属性的值
my_car.update_odometer(23)
print(f"My car has {my_car.odometer_reading} miles on it.")2.3. 增量地修改属性的值
有时候需要将属性值递增特定的量,而不是将其设置为全新的值
python
class Car:
--上面代码不变,下面增加--
def increment_odometer(self, miles):
"""将里程表读数增加指定的量"""
self.odometer_reading += miles
# 使用方法增量地修改属性的值
my_car.increment_odometer(100)
print(f"My car has {my_car.odometer_reading} miles on it.")3. 继承
编写类时,并非总是要从空白开始。如果你要编写的类是另一个现成类的特殊版本,可使用继承。
一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法.
3.1 子类的方法__init__()
下面来创建一个简单的ElectricCar类版本,它具备Car类的所有功能:
python
# 定义子类, 必须指定父类的名称 Car
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year)
# 子类创建实例
my_car = ElectricCar("tesla", "model s", 2019)
# 调用父类的方法
print(my_car.get_descriptive_name()) # 2019 Tesla Model S- 创建子类时,父类必须包含在当前文件中,且位于子类前面
- 定义子类时,必须在括号内指定父类的名称
- 方法__init__()接受创建Car实例所需的信息
- 调用super().init()时,将自动传递实参self。这是必要的,让Python将父类的所有属性都包含到子类中。
3.2 给子类定义属性和方法
python
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year)
self.battery_size = 75 # 电瓶容量 默认值为 75
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print(f"This car has a {self.battery_size}-kWh battery.")
# 子类创建实例
my_car = ElectricCar("tesla", "model s", 2019)
# 调用子类的方法
my_car.describe_battery() # This car has a 75-kWh battery.3.3 重写父类的方法
有时候,父类的方法不符合子类的需求。在这种情况下,可在子类中定义一个同名的方法,用于覆盖父类的方法。
python
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year)
self.battery_size = 75 # 电瓶容量 默认值为 75
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print(f"This car has a {self.battery_size}-kWh battery.")
def get_descriptive_name(self):
"""返回整洁的描述性信息"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
# 子类创建实例
my_car = ElectricCar("tesla", "model s", 2019)
# 调用子类的方法
print(my_car.get_descriptive_name()) # 2019 Tesla Model S3.4 将实例用作属性
将一个类的实例用作另一个类的属性
例如,不断给ElectricCar类添加细节时,我们可能会发现其中包含很多专门针对汽车电瓶的属性和方法。在这种情况下,我们可将这些属性和方法提取出来,放到另一个名为Battery的类中,并将一个Battery实例用作ElectricCar类的一个属性:
python
class Battery:
"""一个简单的电瓶类"""
def __init__(self, battery_size=75):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print(f"This car has a {self.battery_size}-kWh battery.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year)
self.battery = Battery() # 创建一个Battery实例
my_car = ElectricCar("tesla", "model s", 2019)
# 调用子类的方法
my_car.battery.describe_battery() # This car has a 75-kWh battery.4. 导入类
随着你不断地给类添加功能,文件可能变得很长,即便你妥善地使用了继承亦如此。为遵循Python的总体理念,应让文件尽可能整洁。为在这方面提供帮助,Python允许你将类存储在模块中,然后在主程序中导入所需的模块。
和函数的导入类似,类的导入也使用import语句。
- 导入单个类 :
from module_name import class_name - 导入多个类 :
from module_name import class_name_1, class_name_2 - 导入整个模块 :
import module_name
5. Python标准库
Python标准库是一组模块,安装的Python都包含它。你现在对类的工作原理已有大致的了解,可以开始使用其他程序员编写好的模块了。可使用标准库中的任何函数和类,为此只需在程序开头包含一条简单的import语句。
下面来看模块collections中的一个类——OrderedDict。OrderedDict实例的行为几乎与字典相同,区别只在于记录了键—值对的添加顺序。
python
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(f"{name.title()}'s favorite language is {language.title()}.")6. 类编码风格
- 类名应采用
大驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。 - 实例名和模块名都采用小写格式,并在单词之间加上下划线。