Skip to content

面向对象编程是最有效的软件编写方法之一。在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。

编写类时,你定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。

根据类来创建对象被称为实例化,这让你能够使用类的实例。

例如 猫 是一个类, 灰灰是一个实例,有自己的属性和行为。

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 S

3.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. 类编码风格

  • 类名应采用大驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。
  • 实例名和模块名都采用小写格式,并在单词之间加上下划线。

京ICP备2024093538号-1