面向对象高级
类方法
类方法使用@classmethod装饰器定义,它接收类本身作为第一个参数,而不是实例。
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):
from datetime import date
today = date.today()
return cls(today.year, today.month, today.day)
# 使用类方法
date1 = Date(2024, 1, 15)
date2 = Date.from_string("2024-06-20")
date3 = Date.today()
print(date1.year) # 输出: 2024
print(date2.month) # 输出: 6
静态方法
静态方法使用@staticmethod装饰器定义,它不接收类或实例作为参数。
class MathUtils:
@staticmethod
def add(a, b):
return a + b
@staticmethod
def is_even(number):
return number % 2 == 0
@staticmethod
def factorial(n):
if n < 0:
raise ValueError("负数没有阶乘")
if n == 0 or n == 1:
return 1
return n * MathUtils.factorial(n - 1)
# 使用静态方法
print(MathUtils.add(3, 5)) # 输出: 8
print(MathUtils.is_even(4)) # 输出: True
print(MathUtils.factorial(5)) # 输出: 120
属性装饰器
属性装饰器让你可以像访问属性一样调用方法,实现计算属性和数据验证。
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
"""获取半径"""
return self._radius
@radius.setter
def radius(self, value):
"""设置半径,确保为正数"""
if value <= 0:
raise ValueError("半径必须为正数")
self._radius = value
@property
def area(self):
"""计算面积(只读属性)"""
return 3.14159 * self._radius ** 2
@property
def circumference(self):
"""计算周长(只读属性)"""
return 2 * 3.14159 * self._radius
# 使用属性
circle = Circle(5)
print(circle.radius) # 输出: 5
print(circle.area) # 输出: 78.53975
print(circle.circumference) # 输出: 31.4159
circle.radius = 10
print(circle.area) # 输出: 314.159
抽象类
抽象类使用abc模块定义,它不能被实例化,用于定义接口规范。
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
"""计算面积"""
pass
@abstractmethod
def perimeter(self):
"""计算周长"""
pass
def describe(self):
"""非抽象方法,可以有默认实现"""
return f"这是一个形状,面积是{self.area()},周长是{self.perimeter()}"
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)
rectangle = Rectangle(4, 6)
print(circle.describe())
print(rectangle.describe())
数据类
Python 3.7+引入了dataclasses模块,简化类的创建。
from dataclasses import dataclass, field
from typing import List
@dataclass
class Student:
name: str
age: int
grades: List[float] = field(default_factory=list)
@property
def average_grade(self):
if not self.grades:
return 0
return sum(self.grades) / len(self.grades)
def __post_init__(self):
"""初始化后处理"""
if self.age < 0:
raise ValueError("年龄不能为负数")
# 使用数据类
student1 = Student("张三", 20, [85, 90, 95])
student2 = Student("李四", 22)
print(student1) # 输出: Student(name='张三', age=20, grades=[85, 90, 95])
print(student1.average_grade) # 输出: 90.0
枚举类
枚举类用于定义一组命名的常量值。
from enum import Enum, auto
class Color(Enum):
RED = auto()
GREEN = auto()
BLUE = auto()
class Direction(Enum):
NORTH = "北"
SOUTH = "南"
EAST = "东"
WEST = "西"
# 使用枚举
print(Color.RED) # 输出: Color.RED
print(Color.RED.value) # 输出: 1
print(Direction.NORTH.value) # 输出: 北
# 枚举比较
print(Color.RED == Color.RED) # 输出: True
print(Color.RED == Color.GREEN) # 输出: False
最佳实践
- 类方法适用于工厂模式,提供替代的构造方式
- 静态方法适用于与类相关但不需要访问类或实例的工具函数
- 使用属性装饰器实现计算属性和数据验证
- 抽象类用于定义接口规范,确保子类实现必要方法
- 数据类简化了数据容器类的创建,减少样板代码
- 枚举类用于定义一组相关的常量,提高代码可读性
掌握这些高级面向对象特性,能让你写出更加Pythonic的代码。