人工智能之编程进阶 Python高级:第二章 面向对象

Python面向对象高级编程详解

人工智能之编程进阶 Python高级

第二章 面向对象



前言

Python 是一种面向对象编程(Object-Oriented Programming, OOP) 语言,支持封装、继承、多态等核心特性。掌握面向对象编程是编写结构清晰、可维护、可复用代码的关键。


一、面向对象核心概念

概念说明
类(Class)对象的蓝图或模板,定义属性和方法
对象(Object)类的实例,具有具体的状态和行为
封装(Encapsulation)将数据和操作数据的方法绑定在一起,隐藏内部实现
继承(Inheritance)子类继承父类的属性和方法,实现代码复用
多态(Polymorphism)同一接口,不同实现(如方法重写)
抽象(Abstraction)隐藏复杂细节,只暴露必要接口

二、定义类和创建对象

1. 基本语法

class ClassName:
    # 类属性(所有实例共享)
    class_variable = "共享值"

    # 构造方法(初始化)
    def __init__(self, param1, param2):
        # 实例属性(每个对象独有)
        self.instance_var1 = param1
        self.instance_var2 = param2

    # 实例方法
    def method(self):
        return f"{self.instance_var1} - {self.instance_var2}"

# 创建对象(实例化)
obj = ClassName("值1", "值2")
print(obj.method())  # 值1 - 值2

2. __init__ 方法

  • 类似于构造函数,用于初始化对象
  • 第一个参数必须是 self(代表当前实例)
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        return f"Hello, I'm {self.name}, {self.age} years old."

p = Person("Alice", 25)
print(p.greet())  # Hello, I'm Alice, 25 years old.

三、封装与访问控制

Python 没有严格的 private/public 关键字,但通过命名约定实现封装:

命名方式含义访问建议
name公有属性可自由访问
_name受保护属性“内部使用”,但可访问
__name私有属性名称改写(name mangling),外部不可直接访问

示例

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner          # 公有
        self._balance = balance     # 受保护(约定)
        self.__pin = "1234"         # 私有(实际为 _BankAccount__pin)

    def deposit(self, amount):
        if amount > 0:
            self._balance += amount

    def get_balance(self, pin):
        if pin == self.__pin:
            return self._balance
        else:
            raise ValueError("Invalid PIN")

acc = BankAccount("Alice", 100)
print(acc.owner)        # ✅ 可访问
print(acc._balance)     # ⚠️ 可访问,但不推荐
# print(acc.__pin)      # ❌ AttributeError
print(acc._BankAccount__pin)  # ✅ 但强烈不推荐(破坏封装)

✅ ​最佳实践​:使用属性(@property)提供安全的访问接口。

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

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

    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("温度不能低于绝对零度")
        self._celsius = value

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

temp = Temperature(25)
print(temp.celsius)     # 25
print(temp.fahrenheit)  # 77.0
temp.celsius = 30       # 自动验证
# temp.celsius = -300   # 抛出异常

四、继承(Inheritance)

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

1. 基本继承

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        raise NotImplementedError("子类必须实现 speak 方法")

class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak())  # Buddy says Woof!
print(cat.speak())  # Whiskers says Meow!

2. super() 调用父类

class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

class Manager(Employee):
    def __init__(self, name, salary, bonus):
        super().__init__(name, salary)  # 调用父类构造函数
        self.bonus = bonus

    def total_income(self):
        return self.salary + self.bonus

3. 多重继承

class Flyable:
    def fly(self):
        return "Flying..."

class Swimmable:
    def swim(self):
        return "Swimming..."

class Duck(Animal, Flyable, Swimmable):
    def speak(self):
        return "Quack!"

duck = Duck("Donald")
print(duck.fly())    # Flying...
print(duck.swim())   # Swimming...

⚠️ ​注意​:多重继承可能引发 方法解析顺序(MRO) 问题,可通过 ClassName.__mro__ 查看。


五、多态(Polymorphism)

同一接口,不同实现。Python 是动态类型语言,天然支持多态。

def animal_sound(animal: Animal):
    print(animal.speak())  # 不关心具体类型,只要实现 speak()

animals = [Dog("Buddy"), Cat("Whiskers"), Duck("Donald")]
for a in animals:
    animal_sound(a)

输出:

Buddy says Woof!
Whiskers says Meow!
Donald says Quack!

六、特殊方法(魔术方法 / Dunder Methods)

以双下划线开头和结尾的方法,用于自定义类的行为。

方法用途示例
__str__用户友好的字符串表示print(obj)
__repr__开发者友好的字符串表示repr(obj)
__len__支持 len()len(obj)
__getitem__支持索引访问obj[0]
__call__使对象可调用obj()
__eq__定义相等比较obj1 == obj2

示例:自定义容器类

class MyList:
    def __init__(self, items=None):
        self._items = items or []

    def __len__(self):
        return len(self._items)

    def __getitem__(self, index):
        return self._items[index]

    def __str__(self):
        return f"MyList({self._items})"

    def __repr__(self):
        return f"MyList({self._items!r})"

my_list = MyList([1, 2, 3])
print(len(my_list))     # 3
print(my_list[0])       # 1
print(my_list)          # MyList([1, 2, 3])

七、类方法与静态方法

类型装饰器第一个参数用途
实例方法self操作实例数据
类方法@classmethodcls操作类数据,常用于替代构造函数
静态方法@staticmethod与类相关但不依赖类或实例
class Person:
    species = "Homo sapiens"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_species(cls):
        return cls.species

    @classmethod
    def from_string(cls, person_str):
        # 替代构造函数
        name, age = person_str.split('-')
        return cls(name, int(age))

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

# 使用
p1 = Person.from_string("Alice-25")
print(Person.get_species())  # Homo sapiens
print(Person.is_adult(17))   # False

八、抽象基类(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)

# rect = Shape()  # ❌ 不能实例化抽象类
rect = Rectangle(3, 4)
print(rect.area())  # 12

九、数据类(@dataclass,Python 3.7+)

简化只用于存储数据的类。

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float

    def distance_from_origin(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5

p = Point(3.0, 4.0)
print(p)  # Point(x=3.0, y=4.0)
print(p.distance_from_origin())  # 5.0

自动生成 __init__, __repr__, __eq__ 等方法。


十、面向对象设计原则(SOLID 简化版)

  1. 单一职责​:一个类只做一件事
  2. 开闭原则​:对扩展开放,对修改关闭
  3. 里氏替换​:子类能替换父类而不破坏程序
  4. 接口隔离​:客户端不应依赖它不需要的接口
  5. 依赖倒置​:依赖抽象,而非具体实现

十一、super()在 Python 中的作用及使用注意事项

在 Python 中,super() 的核心作用是调用父类(超类)的方法,尤其在继承体系中初始化子类时,它能简洁、安全地触发父类的构造方法(__init__),避免手动硬编码父类名导致的维护问题,同时支持多继承的方法解析顺序(MRO)。

1、先明确:为什么需要 super() 调用父类构造?

当子类定义了自己的 __init__ 方法时,会覆盖父类的__init__(除非主动调用)。如果父类的 __init__ 有必要的初始化逻辑(比如初始化属性、创建资源),子类必须显式触发父类构造,否则父类的属性 / 逻辑不会生效。

反面例子(不推荐):硬编码父类名调用

class Parent:
   def __init__(self, name):
       self.name = name  # 父类初始化核心属性
class Child(Parent):
   def __init__(self, name, age):
       # 硬编码父类名 Parent,若后续父类名修改/继承关系变更,此处会出错
       Parent.__init__(self, name)  # 手动传递 self
       self.age = age  # 子类新增属性
child = Child("小明", 10)
print(child.name)  # 正常输出:小明(但写法不灵活)

问题:如果后续将 Child 的父类改为 NewParent,则 Parent.__init__ 会变成错误调用,维护成本高。

2、super() 构造的核心作用

1. 简洁调用父类构造,解耦父类名

super() 会自动绑定当前类(Child)和实例(self),无需手动写父类名和传递 self,代码更简洁、可维护。

class Parent:
   def __init__(self, name):
       self.name = name
class Child(Parent):
   def __init__(self, name, age):
       # 无需写 Parent,自动找到父类并调用其 __init__
       super().__init__(name)  # 等价于 Parent.__init__(self, name),但更灵活
       self.age = age

child = Child("小红", 12)
print(child.name)  # 输出:小红
print(child.age)   # 输出:12

优势:即使后续修改父类(如 class Child(NewParent):),super() 仍能自动找到正确的父类,无需修改子类代码。

2. 支持多继承的 MRO 顺序(关键作用)

Python 多继承时,方法调用遵循方法解析顺序(MRO)(可通过 类名.__mro__ 查看)。super() 会严格按照 MRO 顺序调用下一个类的方法,避免多继承时的重复调用或调用顺序错误。

例子:多继承中的 super() 协同
class A:
   def __init__(self):
       print("A 的构造方法")
class B(A):
   def __init__(self):
       print("B 的构造方法")
       super().__init__()  # 按 MRO 调用下一个父类(A)

class C(A):
   def __init__(self):
       print("C 的构造方法")
       super().__init__()  # 按 MRO 调用下一个父类(A)
# 多继承:D 继承 B 和 C
class D(B, C):
   def __init__(self):
       print("D 的构造方法")
       super().__init__()  # 按 MRO 调用下一个父类(B)
# 查看 D 的 MRO 顺序:D → B → C → A → object
print(D.__mro__)  # 输出:(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# 实例化 D,观察构造方法调用顺序
d = D()

输出结果

D 的构造方法
B 的构造方法
C 的构造方法
A 的构造方法

关键super() 并非 “调用父类”,而是 “调用 MRO 顺序中的下一个类”。如果不用 super() 而硬编码 B.__init__(self),会跳过 C 的构造,导致多继承逻辑错误。

3. 兼容 Python 2 和 3(显式参数写法)

Python 3 中 super() 可省略参数(默认 super(当前类, self)),但 Python 2 中必须显式传递类和实例:

# Python 2 兼容写法(Python 3 也支持)
class Child(Parent):
   def __init__(self, name, age):
       super(Child, self).__init__(name)  # 显式指定类和实例
       self.age = age

这种写法在多继承中更清晰,明确当前类的 MRO 起点。

3、super() 构造的使用注意事项

  1. 参数匹配:父类 __init__ 所需的参数(除 self 外),子类必须通过 super().__init__(...) 传递,否则会报错。
class Parent:
   def __init__(self, name, gender):
       self.name = name
       self.gender = gender
class Child(Parent):
   def __init__(self, name, gender, age):
       super().__init__(name, gender)  # 必须传递父类所需的 name 和 gender
       self.age = age
  1. 避免循环调用:多继承中,若父类构造未正确使用 super(),可能导致循环调用(需依赖 MRO 自动避免,无需手动处理)。
  2. 单继承 vs 多继承:单继承中 super() 作用是 “解耦父类名”,多继承中是 “遵循 MRO 顺序调用”,后者是其核心价值。
  3. object类的__init__无参数:如果父类是 object(Python 3 中所有类默认继承 object),其 __init__ 不需要参数,若子类 super().__init__() 传递多余参数会报错。

4、总结

super() 构造的核心作用是:

  1. 解耦父类名:避免硬编码父类名,提升代码可维护性;
  2. 遵循 MRO 顺序:在多继承中安全触发所有父类的构造逻辑,避免调用顺序错误;
  3. 简洁传递参数:自动绑定 self,无需手动传递。

最佳实践:只要子类继承了有 __init__ 方法的父类(或多继承场景),都应使用 super().__init__(...) 初始化父类,而非硬编码父类名。


十二、总结

本文主要讲述python的面向对象具有的特性,以便于更加方便的实现业务逻辑以及高效的编程方式,便于理解业务和开发拓展功能。具体内容总结如下

特性Python 实现方式
封装属性命名约定 +@property
继承class Child(Parent):+super()
多态鸭子类型 + 方法重写
抽象abc.ABC+@abstractmethod
便捷数据类@dataclass

✅ ​最佳实践​:

  • 优先组合而非继承
  • 使用 @property 控制属性访问
  • dataclass 简化数据载体类
  • 抽象基类用于定义接口契约

资料关注

相关资料获取:
公众号:咚咚王

《Python编程:从入门到实践》
《利用Python进行数据分析》
《算法导论中文第三版》
《概率论与数理统计(第四版) (盛骤) 》
《程序员的数学》
《线性代数应该这样学第3版》
《微积分和数学分析引论》
《(西瓜书)周志华-机器学习》
《TensorFlow机器学习实战指南》
《Sklearn与TensorFlow机器学习实用指南》
《模式识别(第四版)》
《深度学习 deep learning》伊恩·古德费洛著 花书
《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》
《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen) 》
《自然语言处理综论 第2版》
《Natural-Language-Processing-with-PyTorch》
《计算机视觉-算法与应用(中文版)》
《Learning OpenCV 4》
《AIGC:智能创作时代》杜雨+&+张孜铭
《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》
《从零构建大语言模型(中文版)》
《实战AI大模型》
《AI 3.0》

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咚咚王者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值