Chapter 07

Python基础 · 面向对象编程的核心

欢迎关注微信公众号

coder程 查令十街84号

本章目录

1. 引言:为什么需要类

面向过程用 函数 处理数据,面向对象用 把数据和行为 封装 在一起。

# 面向过程:数据和行为分离 dog_name="Buddy" dog_age=3 defdog_bark(name): print(f"{name} says: 汪!") dog_bark(dog_name)
# 面向对象:数据和行为绑定 classDog: def__init__(self,name,age): self. name=nameself. age=age defbark(self): print(f"{self.name} says: 汪!") buddy= Dog("Buddy",3)buddy. bark() # Buddy says: 汪!

当数据和行为 天然关联 时,面向对象让代码更有组织、更易扩展。

2. 类的定义

类是对象的 蓝图/模板 ,定义了对象有哪些 属性 (数据)和 方法 (行为)。

classStudent: # 类属性:所有实例共享 school="Python学院" # 构造方法:创建实例时自动调用 def__init__(self,name,age): self. name=name # 实例属性 self. age=age # 实例方法 defintroduce(self): returnf"我是{self.name},{self.age}岁" # 类方法 @classmethod deffrom_birth_year(cls,name,birth_year): age=2024-birth_year return cls(name,age)

2. 实例属性、类属性与特殊方法

classCircle: pi=3.14159 # 类属性 def__init__(self,radius): self. radius=radius defarea(self): returnself.pi*self.radius**2 def__str__(self): # 打印对象时的友好输出 returnf"Circle(radius={self.radius})" def__repr__(self): # 交互式环境中的表示 returnf"Circle({self.radius})" def__eq__(self,other): # == 比较逻辑 returnself.radius==other.radius

魔术方法(Dunder Methods) :以双下划线包围,让对象像内置类型一样自然。

3. 创建实例

类本身不会创建数据,需要 实例化 (调用类名)产生对象。

# 创建实例 s1 = Student("Alice", 20) s2 = Student("Bob", 22) # 访问属性 print(s1.name) # Alice print(s1.school) # Python学院(继承自类) # 调用方法 print(s1.introduce()) # 通过类方法创建 s3 = Student.from_birth_year("Carol", 2000)

动态添加属性 :Python 允许运行时给实例添加新属性(但不推荐滥用)。

s1. hobby="编程" print(s1.hobby) # 编程(仅 s1 有,不影响 s2)

3. 封装与属性装饰器

封装 :隐藏内部实现,通过公开接口交互。Python 用 命名约定 (单下划线)表示"私有"。

classBankAccount: def__init__(self,owner,balance=0): self. owner=ownerself._ balance=balance # _ 前缀:约定私有 defdeposit(self,amount): ifamount>0: self._ balance+=amount defget_balance(self): returnself._balance acc= BankAccount("Alice",1000)acc. deposit(500) print(acc.get_balance()) # 1500

@property :把方法变成属性一样访问。

@property defbalance(self): returnself._balance # 使用:acc.balance 而不是 acc.get_balance()

4. 类的继承

继承 :子类自动拥有父类的属性和方法,同时可 扩展 重写

classAnimal: def__init__(self,name): self. name=name defspeak(self): raise NotImplementedError("子类必须实现") classDog(Animal): # Dog 继承 Animal defspeak(self): returnf"{self.name} says: 汪!" classCat(Animal): # Cat 继承 Animal defspeak(self): returnf"{self.name} says: 喵~" d= Dog("Buddy") c= Cat("Kitty") print(d.speak()) # Buddy says: 汪! print(c.speak()) # Kitty says: 喵~

4. super() 与多继承

super() :调用父类的方法,避免显式指定父类名。

classEmployee: def__init__(self,name,salary): self. name=nameself. salary=salary classManager(Employee): def__init__(self,name,salary,department): super(). __init__(name,salary)self. department=department m= Manager("Alice",50000,"IT")

多继承 :Python 支持一个子类继承多个父类,按 MRO(方法解析顺序) 查找。

classA: defmethod(self): print("A") classB(A): defmethod(self): print("B") classC(A): defmethod(self): print("C") classD(B,C): # 多继承 pass d= D()d. method() # B(按 MRO 顺序) print(D.__mro__) # 查看解析顺序

4. 多态 — 同一接口,不同表现

多态让不同的类对同一消息做出 不同的响应 。Python 作为动态语言天然支持。

defanimal_concert(animals): foranimalinanimals: print(animal.speak()) animals=[Dog("Buddy"),Cat("Kitty")] animal_concert(animals) # 输出: # Buddy says: 汪! # Kitty says: 喵~

鸭子类型 :Python 不检查类型,只关心对象是否有需要的方法。

"如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。"

常用魔术方法速查

方法 触发场景
__init__ 对象初始化
__str__ print(obj) / str(obj)
__repr__ 交互式环境 / repr(obj)
__eq__ obj1 == obj2
__lt__ obj1 < obj2
__len__ len(obj)
__getitem__ obj[key]
__call__ obj() 像函数一样调用

综合练习:图书管理系统

classBook: def__init__(self,title,author,isbn): self. title=titleself. author=authorself. isbn=isbnself._ borrowed=False defborrow(self): ifself._borrowed: print(f"《{self.title}》已被借出") else: self._ borrowed=True print(f"成功借阅《{self.title}》") def__str__(self): status="已借出" ifself._borrowed else"在馆"returnf"《{self.title}》({status})"classEBook(Book): def__init__(self,title,author,isbn,format): super(). __init__(title,author,isbn)self. format= formatdef__str__(self):returnf"[电子书] {super().__str__()} [{self.format}]"

本章总结

下一章 ▶