Python面向对象:从入门到精通,这一篇就够了!
深入理解类、对象、继承、多态,写出优雅的Python代码
在Python编程中,面向对象编程(OOP)是一种核心的编程范式。它通过“类”和“对象”来模拟现实世界,让代码更易维护、扩展和复用。今天,我们就来全面介绍Python的面向对象特性,带你从零基础到熟练运用。
一、面向对象的基本概念
什么是对象?
对象是数据和操作数据的方法的集合。例如,一个“汽车”对象有颜色、速度等属性,也有加速、刹车等方法。
什么是类?
类是创建对象的蓝图或模板。它定义了对象应该具有的属性和方法。
打个比方:类就像一张汽车设计图纸,而对象就是根据图纸造出来的真实汽车。
OOP三大特性
- • 封装:把数据和操作隐藏起来,只暴露必要的接口。
- • 继承:一个类可以继承另一个类的属性和方法,实现代码复用。
二、定义类和创建对象
最简单的类
class Dog: passmy_dog = Dog() # 创建对象print(type(my_dog)) # <class '__main__.Dog'>
实例属性与__init__构造方法
__init__是初始化方法,在创建对象时自动调用,用于设置初始属性。
class Dog: def __init__(self, name, age): self.name = name # 实例属性 self.age = age def bark(self): # 实例方法 print(f"{self.name} 在汪汪叫!")dog1 = Dog("旺财", 3)dog1.bark() # 旺财 在汪汪叫!
- •
self 指向当前实例本身,必须作为第一个参数。
类属性 vs 实例属性
class Cat: species = "猫科动物" # 类属性 def __init__(self, name): self.name = name # 实例属性cat1 = Cat("咪咪")cat2 = Cat("小白")print(cat1.species) # 猫科动物print(cat2.species) # 猫科动物Cat.species = "Felis catus" # 通过类修改print(cat1.species) # Felis catus
三、方法类型:实例方法、类方法、静态方法
| | | |
|---|
| | self | |
| @classmethod | cls | |
| @staticmethod | | |
class MyClass: def instance_method(self): print("实例方法", self) @classmethod def class_method(cls): print("类方法", cls) @staticmethod def static_method(): print("静态方法,不依赖类或实例")obj = MyClass()obj.instance_method()MyClass.class_method()MyClass.static_method()
使用场景:
- • 静态方法:工具函数,与类逻辑相关但不依赖实例。
四、封装与访问控制
Python通过命名约定来实现“私有”成员,没有严格的私有机制。
- • 单下划线
_var:约定“受保护的”,内部使用,外部不应直接访问。 - • 双下划线
__var:名称修饰(name mangling),变为 _ClassName__var,实现伪私有。
class BankAccount: def __init__(self, owner, balance): self.owner = owner self.__balance = balance # 私有属性 def deposit(self, amount): if amount > 0: self.__balance += amount def get_balance(self): # 公开的 getter return self.__balanceacc = BankAccount("张三", 1000)# print(acc.__balance) # 报错:AttributeErrorprint(acc.get_balance()) # 1000print(acc._BankAccount__balance) # 1000,但不建议这样访问
原则:不要过度使用私有属性,Python倡导“我们都是成年人”,通过文档和约定来规范。
五、继承
子类可以继承父类的属性和方法,并能添加或覆盖。
单继承
class Animal: def __init__(self, name): self.name = name def speak(self): print(f"{self.name} 发出声音")class Dog(Animal): def speak(self): # 方法重写 print(f"{self.name} 汪汪叫")dog = Dog("小黑")dog.speak() # 小黑 汪汪叫
使用 super() 调用父类方法
class Cat(Animal): def __init__(self, name, color): super().__init__(name) # 调用父类构造 self.color = color def speak(self): super().speak() # 调用父类方法 print(f"{self.name} 喵喵喵")cat = Cat("橘猫", "橘色")cat.speak()# 橘猫 发出声音# 橘猫 喵喵喵
多重继承与MRO
Python支持多重继承,方法解析顺序(MRO)使用C3线性化算法,可通过 类.__mro__ 查看。
class A: def method(self): print("A")class B(A): def method(self): print("B")class C(A): def method(self): print("C")class D(B, C): passd = D()d.method() # Bprint(D.__mro__) # (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
慎重使用多重继承,避免“钻石继承”带来的混乱。
六、多态
多态指同一个方法在不同类中表现不同行为。Python是动态类型语言,天然支持多态。
class Duck: def sound(self): print("嘎嘎嘎")class Person: def sound(self): print("你好呀")def make_sound(obj): obj.sound()duck = Duck()person = Person()make_sound(duck) # 嘎嘎嘎make_sound(person) # 你好呀
不需要显式继承,只要对象有 sound 方法,就可以传入 make_sound。这就是鸭子类型:“如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。”
七、特殊方法(魔术方法)
特殊方法允许类模拟内置类型的行为,通常以双下划线开头和结尾。
常用的魔术方法
| | |
|---|
__init__(self) | | Class() |
__str__(self) | | print(obj) |
__repr__(self) | | repr(obj) |
__len__(self) | | len(obj) |
__getitem__(self, key) | | obj[key] |
__call__(self) | | obj() |
__add__(self, other) | | obj1 + obj2 |
示例:实现一个简单的Vector类
class Vector: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"Vector({self.x}, {self.y})" def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __len__(self): return int((self.x**2 + self.y**2)**0.5) # 模长取整v1 = Vector(3, 4)v2 = Vector(1, 2)v3 = v1 + v2print(v3) # Vector(4, 6)print(len(v1)) # 5
八、属性装饰器:@property
@property 将方法变成属性调用,并可以定义setter/deleter,实现更优雅的封装。
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 ** 2c = Circle(5)print(c.radius) # 5c.radius = 10print(c.area) # 314.159# c.area = 100 # 报错,没有setter
九、抽象基类(ABC)
抽象基类用于定义接口,强制子类实现特定方法。
from abc import ABC, abstractmethodclass Shape(ABC): @abstractmethod def area(self): passclass Rectangle(Shape): def __init__(self, w, h): self.w = w self.h = h def area(self): return self.w * self.h# s = Shape() # 错误:不能实例化抽象类r = Rectangle(3, 4)print(r.area()) # 12
十、最佳实践与常见误区
✅ 最佳实践
- 2. 尽量使用组合而非继承:当“有一个”而不是“是一个”关系时,用组合。
- 4. 善用
super() 保证多重继承时的协作。 - 5. 使用
@property 替代直接暴露属性,保留后期控制能力。
❌ 常见误区
- • 误解
self:它不是关键字,只是约定名称,改叫 this 也可以。 - • 在类属性中使用可变对象(如列表),会被所有实例共享导致意外。
- • 过度使用私有属性(
__var),反而降低可读性。
十一、综合案例:员工管理系统
下面用一个简单案例串联大部分知识:
class Employee: """员工基类""" company = "XX科技有限公司" def __init__(self, name, salary): self.name = name self._salary = salary # 受保护 @property def salary(self): return self._salary @salary.setter def salary(self, value): if value < 0: raise ValueError("工资不能为负") self._salary = value def work(self): print(f"{self.name} 正在工作") @classmethod def change_company(cls, new_name): cls.company = new_name @staticmethod def is_workday(day): return day not in (6, 7) def __str__(self): return f"{self.name}, 工资: {self.salary}"class Manager(Employee): """经理,继承自Employee""" def __init__(self, name, salary, bonus): super().__init__(name, salary) self.bonus = bonus def work(self): # 多态 print(f"{self.name} 正在管理团队") @property def total_income(self): return self.salary + self.bonus# 使用emp = Employee("张三", 5000)mgr = Manager("李四", 8000, 2000)emp.work() # 张三 正在工作mgr.work() # 李四 正在管理团队print(mgr.total_income) # 10000print(Employee.company) # XX科技有限公司Employee.change_company("YY科技")print(Employee.company) # YY科技
结语
Python的面向对象并不追求严格的封装和复杂的继承体系,而是以简洁、灵活为美。掌握类、继承、多态、魔术方法等概念,你就能写出结构清晰、易于维护的代码。
建议初学者多动手练习,从模仿到创造,逐步体会OOP带来的好处。如果你觉得这篇文章有帮助,欢迎点赞、在看、转发,让更多人学习Python面向对象!
你在使用Python面向对象时遇到过什么困惑?欢迎留言讨论!