Python 编程 - 面向对象编程

面向对象编程是一种程序设计范式,它将数据(属性)和操作(方法)封装在“对象”中。Python 从设计之初就是一门面向对象的语言,在 Python 3 中,OOP 的语法和特性更加完善和一致。下面系统性地介绍 Python 3 中 OOP 的核心概念和用法。


1. 类与对象

类(Class) 是创建对象的蓝图,对象(Object) 是类的实例。

class Dog:
    # 类属性(所有实例共享)
    species = "Canis familiaris"

    # 初始化方法(构造器)
    def __init__(self, name, age):
        self.name = name      # 实例属性
        self.age = age

    # 实例方法
    def bark(self):
        return f"{self.name} says woof!"

# 创建对象
my_dog = Dog("Buddy", 3)
print(my_dog.bark())        # Buddy says woof!
print(my_dog.species)       # Canis familiaris
  • __init__ 是特殊方法,在对象创建时自动调用,用于设置初始状态。
  • self 指向当前实例,必须作为实例方法的第一个参数。

2. 继承

继承允许子类复用父类的属性和方法,并可以扩展或重写。

单继承

class Puppy(Dog):
    def __init__(self, name, age, training_level):
        super().__init__(name, age)   # 调用父类初始化
        self.training_level = training_level

    def bark(self):                   # 重写父类方法
        return f"{self.name} says yip!"

p = Puppy("Max", 1, "beginner")
print(p.bark())        # Max says yip!

多重继承:Python 支持多重继承,方法解析顺序(MRO)遵循 C3 线性化算法,可通过 类.__mro__ 查看。

class Flyer:
    def fly(self):
        print("Flying")

class Swimmer:
    def swim(self):
        print("Swimming")

class Duck(Flyer, Swimmer):
    pass

d = Duck()
d.fly()   # Flying
d.swim()  # Swimming

super():在 Python 3 中,super() 可以不传参数,自动在 MRO 中查找下一个类,推荐使用。


3. 封装与访问控制

Python 没有严格的私有关键字,通过命名约定实现“保护”和“私有”:

  • _single_leading_underscore:约定为“保护”属性,不应直接访问(但解释器不强制)。
  • __double_leading_underscore:名称修饰(name mangling),在类内部会变形为 _ClassName__attr,防止子类意外覆盖。
class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner
        self.__balance = balance   # 私有属性

    def deposit(self, amount):
        self.__balance += amount

    def get_balance(self):         # 通过方法访问
        return self.__balance

acc = BankAccount("Alice", 1000)
# print(acc.__balance)  # AttributeError
print(acc._BankAccount__balance)  # 1000(但不应这样用)

4. 属性装饰器(@property

@property 将方法转换为属性调用,实现更优雅的 getter/setter,同时可以添加验证逻辑。

class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("Temperature below absolute zero!")
        self._celsius = value

    @property
    def fahrenheit(self):
        return self._celsius * 9/5 + 32

t = Temperature(25)
print(t.celsius)      # 25
t.celsius = 30        # 调用 setter
print(t.fahrenheit)   # 86.0

5. 多态与鸭子类型

多态指不同对象对同一消息作出不同响应。Python 通过“鸭子类型”实现:只要对象具有所需的方法或属性,就可以被使用,而不在乎其具体类型。

class Cat:
    def speak(self):
        return "Meow"

class Dog:
    def speak(self):
        return "Woof"

def animal_sound(animal):
    print(animal.speak())

animal_sound(Cat())   # Meow
animal_sound(Dog())   # Woof

6. 特殊方法(魔术方法)

特殊方法(以双下划线开头和结尾)使自定义类能融入 Python 的内置行为。

常用特殊方法:

方法 用途
__init__(self, ...) 初始化对象
__str__(self) 用于 print()str()
__repr__(self) 用于交互式环境和 repr(),应尽量准确可重建
__len__(self) 用于 len()
__getitem__(self, key) 实现索引访问
__add__(self, other) 实现 + 运算符
__call__(self, ...) 使对象可被调用
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2
print(v3)  # Vector(4, 6)

7. 类方法与静态方法

  • @classmethod:方法接收类本身(cls)作为第一个参数,通常用于工厂方法。
  • @staticmethod:不接收隐式的第一个参数,行为类似普通函数,但放在类中便于组织。
class Person:
    population = 0

    def __init__(self, name):
        self.name = name
        Person.population += 1

    @classmethod
    def from_birth_year(cls, name, birth_year):
        age = 2026 - birth_year   # 假设当前年份
        return cls(name, age)     # 实际上需要调整 __init__,演示用

    @staticmethod
    def is_adult(age):
        return age >= 18

p = Person.from_birth_year("Bob", 2000)
print(Person.is_adult(20))  # True

8. 抽象基类(ABC)

抽象基类用于定义接口,强制子类实现某些方法。使用 abc 模块。

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

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)

# s = Shape()  # TypeError: Can't instantiate abstract class Shape
r = Rectangle(3, 4)
print(r.area())  # 12

9. 数据类(dataclasses

Python 3.7 引入 dataclasses,自动生成 __init____repr____eq__ 等常用方法,减少样板代码。

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float
    label: str = "origin"   # 默认值

    def distance_from(self, other):
        return ((self.x - other.x)**2 + (self.y - other.y)**2)**0.5

p1 = Point(1, 2)
p2 = Point(4, 6)
print(p1)                # Point(x=1, y=2, label='origin')
print(p1.distance_from(p2))  # 5.0

dataclass 还支持 frozen=True(不可变)、order=True(比较排序)等参数。


10. 类型提示与 OOP

虽然 Python 是动态类型,但支持类型提示(PEP 484),结合 typing 模块可以提高代码可读性和工具支持。

from typing import List

class ShoppingCart:
    def __init__(self, items: List[str]) -> None:
        self.items = items

    def add_item(self, item: str) -> None:
        self.items.append(item)

    def get_items(self) -> List[str]:
        return self.items

类型提示不影响运行时行为,但配合静态检查工具(如 mypy)能发现类型错误。


11. Python 3 相对于 Python 2 的主要 OOP 变化

  • super() 不再需要参数,更简洁。
  • 元类语法改变:使用 class MyClass(metaclass=MyMeta) 替代 __metaclass__ 属性。
  • 新增 dataclasses@dataclass
  • 类型提示标准库 typing 引入。
  • 所有类默认继承 object(新式类统一)。

总结

Python 3 中的 OOP 设计既直观又强大。它融合了经典的类机制、灵活的多重继承、强大的特殊方法以及现代的语法糖(如数据类和属性装饰器)。理解这些概念能帮助你编写出结构清晰、可扩展的代码。在实践中,根据项目需求选择合适的 OOP 风格——从简单的类到完整的抽象接口,Python 都提供了完备的支持。

posted @ 2026-06-21 10:26  箫笛  阅读(16)  评论(0)    收藏  举报