Python类——进阶

1. 抽象类的定义与实现

什么是抽象类?

抽象类是一种不能被实例化的类,它的主要作用是定义接口和规范,强制子类实现特定的方法。在Python中,抽象类通过abc模块(Abstract Base Classes)来实现。

使用abc模块创建抽象基类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from abc import ABC, abstractmethod

class Animal(ABC):
"""动物抽象基类"""

@abstractmethod
def eat(self):
"""吃方法"""
pass

@abstractmethod
def sleep(self):
"""睡觉方法"""
pass

def breathe(self):
"""呼吸方法(非抽象方法,有默认实现)"""
print("Breathing...")

抽象类的继承规则

  1. 子类必须实现所有抽象方法,否则子类也会成为抽象类
  2. 子类可以重写非抽象方法
  3. 抽象类可以包含非抽象方法(带有默认实现)

实际应用场景

  • 定义接口规范,确保所有子类都实现特定方法
  • 提供通用的方法实现,减少代码重复
  • 实现多态,通过抽象基类统一处理不同的实现

完整实现示例

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
36
37
38
39
40
41
42
43
44
45
46
from abc import ABC, abstractmethod

class Shape(ABC):
"""形状抽象基类"""

@abstractmethod
def area(self):
"""计算面积"""
pass

@abstractmethod
def perimeter(self):
"""计算周长"""
pass

class Circle(Shape):
"""圆形类"""
def __init__(self, radius):
self.radius = radius

def area(self):
return 3.14159 * self.radius ** 2

def perimeter(self):
return 2 * 3.14159 * self.radius

class Rectangle(Shape):
"""矩形类"""
def __init__(self, width, height):
self.width = width
self.height = height

def area(self):
return self.width * self.height

def perimeter(self):
return 2 * (self.width + self.height)

# 测试
circle = Circle(5)
print(f"Circle area: {circle.area()}")
print(f"Circle perimeter: {circle.perimeter()}")

rectangle = Rectangle(4, 6)
print(f"Rectangle area: {rectangle.area()}")
print(f"Rectangle perimeter: {rectangle.perimeter()}")

2. 私有方法与属性

命名规范

Python中没有真正的私有成员,而是通过命名约定来实现:

  • 单下划线前缀(如_private):表示保护成员,建议外部不要直接访问
  • 双下划线前缀(如__private):表示私有成员,会触发名称修饰(name mangling)

名称修饰机制

当使用双下划线前缀时,Python会自动将名称修改为_ClassName__private的形式,这样可以避免子类中的命名冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyClass:
def __init__(self):
self._protected = "protected"
self.__private = "private"

def _protected_method(self):
return "This is a protected method"

def __private_method(self):
return "This is a private method"

obj = MyClass()
print(obj._protected) # 可以访问
# print(obj.__private) # 会报错
print(obj._MyClass__private) # 可以通过修饰后的名称访问

print(obj._protected_method()) # 可以调用
# print(obj.__private_method()) # 会报错
print(obj._MyClass__private_method()) # 可以通过修饰后的名称调用

私有成员的间接访问

可以通过公共方法来间接访问私有成员:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age

def get_age(self):
return self.__age

def set_age(self, age):
if age > 0:
self.__age = age
else:
raise ValueError("Age must be positive")

person = Person("Alice", 30)
print(person.get_age()) # 输出: 30
person.set_age(31)
print(person.get_age()) # 输出: 31
# person.__age = 25 # 这不会修改私有属性,而是创建一个新的公共属性
print(person.get_age()) # 输出: 31

3. 类相关常用注解

@classmethod

作用:定义类方法,第一个参数是类本身(通常命名为cls

使用场景

  • 当方法需要访问或修改类级别的属性时
  • 作为工厂方法创建类的实例
  • 提供与类相关的工具方法

语法格式

1
2
3
4
class MyClass:
@classmethod
def class_method(cls, param1, param2):
# 方法实现

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day

@classmethod
def from_string(cls, date_string):
"""从字符串创建日期对象"""
year, month, day = map(int, date_string.split('-'))
return cls(year, month, day)

@classmethod
def today(cls):
"""获取今天的日期"""
import datetime
today = datetime.date.today()
return cls(today.year, today.month, today.day)

# 使用
date1 = Date(2023, 12, 25)
date2 = Date.from_string("2023-12-25")
date3 = Date.today()

@staticmethod

作用:定义静态方法,不接收特殊的第一个参数(既不是self也不是cls

使用场景

  • 当方法不需要访问实例或类的属性时
  • 提供与类相关但独立于实例的功能
  • 作为工具方法

语法格式

1
2
3
4
class MyClass:
@staticmethod
def static_method(param1, param2):
# 方法实现

示例

1
2
3
4
5
6
7
8
9
10
11
12
class MathUtils:
@staticmethod
def add(a, b):
return a + b

@staticmethod
def multiply(a, b):
return a * b

# 使用
result1 = MathUtils.add(5, 3)
result2 = MathUtils.multiply(5, 3)

@property

作用:将方法转换为属性,使得可以像访问属性一样调用方法

使用场景

  • 实现属性的getter方法
  • 对属性访问进行控制和验证
  • 计算属性值

语法格式

1
2
3
4
5
6
7
8
class MyClass:
@property
def property_name(self):
# getter实现

@property_name.setter
def property_name(self, value):
# setter实现

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Person:
def __init__(self, name, age):
self.name = name
self._age = age

@property
def age(self):
return self._age

@age.setter
def age(self, value):
if value > 0:
self._age = value
else:
raise ValueError("Age must be positive")

# 使用
person = Person("Bob", 25)
print(person.age) # 调用getter
person.age = 26 # 调用setter
print(person.age) # 调用getter

@abstractmethod

作用:定义抽象方法,强制子类实现

使用场景

  • 在抽象基类中定义必须由子类实现的方法
  • 确保所有子类都遵循相同的接口

语法格式

1
2
3
4
5
6
from abc import ABC, abstractmethod

class MyAbstractClass(ABC):
@abstractmethod
def abstract_method(self):
pass

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from abc import ABC, abstractmethod

class Vehicle(ABC):
@abstractmethod
def start(self):
pass

@abstractmethod
def stop(self):
pass

class Car(Vehicle):
def start(self):
print("Car starting...")

def stop(self):
print("Car stopping...")

class Bike(Vehicle):
def start(self):
print("Bike starting...")

def stop(self):
print("Bike stopping...")

4. 项目工程中的类定义规范

命名规范

  • 类名:使用大驼峰命名法(PascalCase),如MyClass
  • 方法名:使用小驼峰命名法(camelCase),如myMethod
  • 属性名:使用小驼峰命名法,如myProperty
  • 私有成员:使用单下划线或双下划线前缀,如_private__private
  • 常量:使用全大写字母和下划线,如MAX_VALUE

代码组织结构

  • 每个模块(.py文件)应该包含相关的类和函数
  • 类应该按照逻辑关系组织,相关的类放在同一个模块中
  • 大型项目应该使用包(package)来组织模块
  • 合理使用继承和组合,避免过度继承

文档字符串格式

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 MyClass:
"""类的文档字符串

详细描述类的功能、用途和使用方法

Attributes:
attribute1 (type): 描述
attribute2 (type): 描述
"""

def my_method(self, param1, param2):
"""方法的文档字符串

详细描述方法的功能、参数和返回值

Args:
param1 (type): 参数描述
param2 (type): 参数描述

Returns:
type: 返回值描述

Raises:
ExceptionType: 异常描述
"""
# 方法实现

类继承关系设计原则

  1. 单一职责原则:一个类应该只负责一项功能
  2. 开闭原则:对扩展开放,对修改关闭
  3. 里氏替换原则:子类应该能够替换父类
  4. 接口隔离原则:使用多个专门的接口而不是一个宽泛的接口
  5. 依赖倒置原则:依赖于抽象,而不是具体实现

实际项目示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# project/utils/validators.py
class Validator:
"""验证器基类"""
def validate(self, value):
"""验证值"""
pass

class EmailValidator(Validator):
"""邮箱验证器"""
def validate(self, value):
# 邮箱验证逻辑
pass

# project/models/user.py
class User:
"""用户类"""
def __init__(self, name, email):
self.name = name
self.email = email

def validate(self):
"""验证用户数据"""
validator = EmailValidator()
return validator.validate(self.email)

5. Python类之间的设计模式

单例模式

适用场景:当只需要一个类的实例时,如配置管理、数据库连接池等

实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Singleton:
_instance = None

def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance

class Database(Singleton):
def __init__(self, connection_string):
if not hasattr(self, 'initialized'):
self.connection_string = connection_string
self.initialized = True

# 使用
db1 = Database("localhost:5432")
db2 = Database("localhost:5432")
print(db1 is db2) # 输出: True

工厂模式

适用场景:当需要根据不同条件创建不同类型的对象时

实现方式

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
from abc import ABC, abstractmethod

class Product(ABC):
@abstractmethod
def operation(self):
pass

class ConcreteProductA(Product):
def operation(self):
return "Product A operation"

class ConcreteProductB(Product):
def operation(self):
return "Product B operation"

class Factory:
def create_product(self, product_type):
if product_type == "A":
return ConcreteProductA()
elif product_type == "B":
return ConcreteProductB()
else:
raise ValueError(f"Unknown product type: {product_type}")

# 使用
factory = Factory()
product_a = factory.create_product("A")
product_b = factory.create_product("B")
print(product_a.operation()) # 输出: Product A operation
print(product_b.operation()) # 输出: Product B operation

观察者模式

适用场景:当一个对象的状态变化需要通知其他对象时

实现方式

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
36
37
38
39
class Subject:
def __init__(self):
self.observers = []

def attach(self, observer):
if observer not in self.observers:
self.observers.append(observer)

def detach(self, observer):
if observer in self.observers:
self.observers.remove(observer)

def notify(self):
for observer in self.observers:
observer.update(self)

class Observer:
def update(self, subject):
pass

class ConcreteObserverA(Observer):
def update(self, subject):
print(f"Observer A received update from {subject}")

class ConcreteObserverB(Observer):
def update(self, subject):
print(f"Observer B received update from {subject}")

# 使用
subject = Subject()
observer_a = ConcreteObserverA()
observer_b = ConcreteObserverB()

subject.attach(observer_a)
subject.attach(observer_b)
subject.notify()

subject.detach(observer_a)
subject.notify()

装饰器模式

适用场景:当需要动态地为对象添加额外的功能时

实现方式

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
from abc import ABC, abstractmethod

class Component(ABC):
@abstractmethod
def operation(self):
pass

class ConcreteComponent(Component):
def operation(self):
return "ConcreteComponent operation"

class Decorator(Component):
def __init__(self, component):
self.component = component

def operation(self):
return self.component.operation()

class ConcreteDecoratorA(Decorator):
def operation(self):
return f"ConcreteDecoratorA({self.component.operation()})"

class ConcreteDecoratorB(Decorator):
def operation(self):
return f"ConcreteDecoratorB({self.component.operation()})"

# 使用
component = ConcreteComponent()
decorator_a = ConcreteDecoratorA(component)
decorator_b = ConcreteDecoratorB(decorator_a)
print(decorator_b.operation()) # 输出: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent operation))

总结

Python类的进阶特性为我们提供了强大的面向对象编程能力,包括:

  1. 抽象类:通过abc模块实现,强制子类实现特定方法,定义接口规范
  2. 私有成员:通过命名约定实现,保护类的内部状态
  3. 类注解:如@classmethod、@staticmethod、@property等,提供了更灵活的方法定义方式
  4. 工程规范:良好的命名、组织和文档规范,提高代码质量和可维护性
  5. 设计模式:如单例模式、工厂模式、观察者模式等,解决常见的设计问题

掌握这些进阶特性,可以帮助我们编写更加优雅、高效、可维护的Python代码。在实际项目开发中,应该根据具体需求选择合适的特性和设计模式,遵循最佳实践,构建高质量的软件系统。