Python之面向对象详解(一篇足矣)

Python 面向对象编程(OOP)详解:一篇足矣(2026 年实用版)

前言:Python 的面向对象编程(OOP)是其核心特性之一,让代码更模块化、可复用、可维护。OOP 三大支柱:封装(Encapsulation)继承(Inheritance)多态(Polymorphism)。如果你是新手,别担心,我们从 0 基础开始,由浅入深。教程基于 Python 3.12+,包含代码示例(直接复制运行)。学完这篇,你能自信写出 80% 实际项目中的 OOP 代码。

我们分成这些模块学(建议按顺序):

  1. OOP 基础概念
  2. 类和对象创建
  3. 属性与方法
  4. 继承与多态
  5. 封装与访问控制
  6. 特殊方法(魔法方法)
  7. 类变量 vs 实例变量、静态/类方法
  8. 高级话题(抽象类、接口、多继承)
  9. 常见错误 & 最佳实践
  10. 小练习 & 面试题

1. OOP 基础概念(为什么用 OOP?)

  • 类(Class):蓝图/模板,比如“汽车”类定义了所有汽车的共同特征(颜色、速度)和行为(开车、刹车)。
  • 对象(Object):类的实例,比如一辆具体的“红色特斯拉”。
  • 为什么用 OOP
  • 复用:写一次类,到处创建对象。
  • 组织:大项目分模块。
  • 抽象:隐藏复杂细节,只露接口。
  • 生活比喻:类 = 手机模具,对象 = 你手里的 iPhone。

一句话:一切皆对象(Python 哲学),int、str、list 都是内置类。


2. 类和对象创建(最简单起步)

class 关键字定义类。

# 定义类(类名首字母大写,驼峰式)
class Dog:
    pass  # 空类,占位

# 创建对象(实例化)
my_dog = Dog()  # my_dog 是 Dog 的实例
print(type(my_dog))  # 输出: <class '__main__.Dog'>

进阶:带初始化方法(__init__)。

class Dog:
    def __init__(self, name, age):  # self 是实例自身(必须第一个参数)
        self.name = name  # 实例属性
        self.age = age

# 创建对象
my_dog = Dog("旺财", 3)
print(my_dog.name)  # 输出: 旺财

Tips__init__ 不是构造函数(Python 没有严格构造函数),而是初始化方法。类定义时不执行,实例化时自动调用。


3. 属性与方法(类的核心内容)

  • 属性(Attribute):数据(如 name、age)。
  • 方法(Method):行为(如 bark、run)。
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def bark(self):  # 方法,self 必备
        print(f"{self.name} 汪汪叫!")

    def run(self, speed):
        print(f"{self.name} 以 {speed} km/h 跑!")

my_dog = Dog("旺财", 3)
my_dog.bark()  # 输出: 旺财 汪汪叫!
my_dog.run(20)  # 输出: 旺财 以 20 km/h 跑!

属性分类

  • 实例属性:每个对象独立(如 self.name)。
  • 类属性:所有对象共享(见第 7 节)。

方法调用:总是 对象.方法(),内部用 self 访问属性。


4. 继承与多态(代码复用神器)

  • 继承:子类继承父类属性/方法,可扩展/覆盖。
class Animal:  # 父类(基类)
    def __init__(self, species):
        self.species = species

    def eat(self):
        print("吃东西...")

class Dog(Animal):  # 子类(派生类),继承 Animal
    def __init__(self, name, age):
        super().__init__("狗")  # 调用父类 __init__
        self.name = name
        self.age = age

    def bark(self):
        print(f"{self.name} 汪汪!")

    def eat(self):  # 方法覆盖(重写)
        print(f"{self.name} 吃骨头!")  # 多态体现

my_dog = Dog("旺财", 3)
my_dog.eat()  # 输出: 旺财 吃骨头!(覆盖父类)
print(my_dog.species)  # 输出: 狗(继承父类)
  • 多态:不同子类用同名方法,行为不同(鸭子类型)。
class Cat(Animal):
    def eat(self):
        print("吃鱼!")

animals = [Dog("旺财", 3), Cat()]  # Cat 需加 __init__,这里省略
for animal in animals:
    animal.eat()  # 多态:狗吃骨头,猫吃鱼

super():调用父类方法,Python 3 推荐无参数形式。


5. 封装与访问控制(隐藏细节)

  • 封装:把数据/方法打包,隐藏内部实现。
  • Python 无严格私有(约定俗成用 _ 或 __)。
访问级别写法说明
公有name外部可直接访问
保护(约定)_name子类可访问,外部不建议
私有(伪)__name名称改写为 _Class__name,外部难访问
class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # 私有属性

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

    def get_balance(self):  # getter 方法
        return self.__balance

account = BankAccount(100)
print(account.get_balance())  # 100
# print(account.__balance)  # AttributeError(但可通过 _BankAccount__balance 访问,勿滥用)

@property(优雅 getter/setter,C++ 无等价):

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

c = Circle(5)
print(c.radius)  # 5(像属性访问)
c.radius = 10    # setter 调用

6. 特殊方法(魔法方法,Python OOP 的灵魂)

这些以 __ 开头的双下划线方法,让类像内置类型一样行为。

常见魔法方法作用示例代码
init初始化如上
strprint 时调用return f”Dog: {self.name}”
reprrepr() 或调试时return f”Dog(‘{self.name}’, {self.age})”
lenlen(obj)return 长度
getitemobj[key]支持索引如列表
callobj() 如函数调用def call(self): print(“调用!”)
addobj1 + obj2return self.value + other.value
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 __str__(self):
        return f"({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)  # 输出: (4, 6)

Tips:魔法方法让类“鸭子类型”兼容(如自定义类支持 + 操作符)。


7. 类变量 vs 实例变量、静态/类方法

  • 类变量:类级共享,所有实例共用。
  • 实例变量:每个实例独立。
class Dog:
    species = "狗"  # 类变量

    def __init__(self, name):
        self.name = name  # 实例变量

d1 = Dog("旺财")
d2 = Dog("小黑")
print(d1.species, d2.species)  # 狗 狗
Dog.species = "Canine"  # 修改类变量,所有实例变
print(d1.species)  # Canine
  • 静态方法:不访问 self/class,用 @staticmethod。
  • 类方法:访问类,用 @classmethod,第一个参数 cls。
class MathUtil:
    @staticmethod
    def add(a, b):
        return a + b  # 无 self/cls

    @classmethod
    def from_string(cls, s):
        return cls()  # cls 是类自身,可创建实例

print(MathUtil.add(1, 2))  # 3(像函数调用)

8. 高级话题(抽象类、接口、多继承)

  • 抽象类:不能实例化,强制子类实现方法。用 abc 模块。
from abc import ABC, abstractmethod

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

class Rectangle(Shape):
    def __init__(self, w, h):
        self.w, self.h = w, h

    def area(self):
        return self.w * self.h

r = Rectangle(2, 3)
print(r.area())  # 6
# Shape()  # TypeError: Can't instantiate abstract class
  • 接口:Python 无正式接口,但用抽象类模拟(全抽象方法)。
  • 多继承:支持,但小心菱形问题(MRO 方法解析顺序)。
class A: pass
class B: pass
class C(A, B): pass  # 多继承
print(C.mro())  # [<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>]

菱形继承:用 super() 解决调用顺序。


9. 常见错误 & 最佳实践

错误类型描述 & 修复
忘记 self方法参数漏 self → TypeError
修改类变量误改实例self.species = “猫” 只改实例,非类
init 拼写错int 等 → 不调用
继承时漏 super()父类属性未初始化
多继承 MRO 混乱用 super(),检查 mro()

最佳实践

  • 类小而专一(单一职责原则)。
  • 用 dataclass (Python 3.7+) 简化 boilerplate。
  • 优先组合 > 继承。
  • 文档字符串(docstring)描述类/方法。
  • 类型提示(typing 模块)提升可读性。
from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int  # 自动生成 __init__、__repr__ 等

10. 小练习 & 面试题

练习1:写一个 BankAccount 类,支持存款、取款、查询余额(用私有属性 + getter)。

练习2:实现一个 Shape 抽象类,子类 Circle 和 Rectangle 计算面积、周长。

面试题

  • 解释 self 和 cls 的区别?
  • Python 如何实现多态?
  • newinit 区别?(new 创建实例,init 初始化)
  • 什么是元类(metaclass)?(类的类,type 是默认元类)

学完这些,你已掌握 Python OOP 90% 精髓!如果你想:

  • 看完整练习答案?
  • 深入某个话题(如元类、装饰器在 OOP 中的用)?
  • 对比 Python OOP 与 C++/Java 的异同?
  • 还是来点项目实战(如 OOP 实现的游戏)?

告诉我,继续陪你升级~ 😊

文章已创建 4323

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部