当前位置:首页>python>Python教程 — 面向对象编程(OOP)

Python教程 — 面向对象编程(OOP)

  • 2026-10-11 06:23:27
Python教程 — 面向对象编程(OOP)

> 如果你只会面向过程写 Python,那你只用出了它 50% 的威力。今天聊聊什么是面向对象编程。

---

## 一、为什么要学面向对象?

想象一下:

-**面向过程**:做一顿饭,从洗菜、切菜、炒菜到摆盘,一步一步写到底

-**面向对象**:你有 `厨师`、`切菜机`、`燃气灶` 这些"对象",每个对象自带方法,你只需要协调它们

随着程序变大,面向对象的 **可维护性、复用性、扩展性** 优势就体现出来了。

---

## 二、类与对象的基本概念

### 2.1 定义一个类

```python

classDog:

"""代表一只狗"""

# 类属性(所有实例共享)

    species = "Canis familiaris"

# 构造方法

def__init__(self, name, age):

# 实例属性(每个实例独立)

self.name = name

self.age = age

# 实例方法

defbark(self):

returnf"{self.name} 说:汪汪汪!"

defget_info(self):

returnf"{self.name},{self.age}岁,{self.species}"

# 创建对象(实例)

dog1 = Dog("小白", 3)

dog2 = Dog("小黑", 5)

print(dog1.bark())   # 小白 说:汪汪汪!

print(dog2.get_info())  # 小黑,5岁,Canis familiaris

```

>**关键理解**:

>-`class Dog` 定义了模板

>-`__init__` 是构造函数,实例化时自动调用

>-`self` 指向实例本身(类似 JavaScript 的 `this`,Java 的 `this`)

>- 实例方法第一个参数必须是 `self`

### 2.2 类属性 vs 实例属性

```python

classCompany:

    company_name = "ABC科技"# 类属性

def__init__(self, employee_name):

self.employee_name = employee_name  # 实例属性

emp1 = Company("张三")

emp2 = Company("李四")

print(emp1.company_name)   # ABC科技(类属性)

print(emp1.employee_name)  # 张三(实例属性)

print(emp2.employee_name)  # 李四(实例属性)

# 修改类属性会影响所有实例

Company.company_name = "XYZ集团"

print(emp1.company_name)  # XYZ集团

```

---

## 三、封装——隐藏内部细节

### 3.1 基本的封装

```python

classBankAccount:

"""银行账户"""

def__init__(self, owner, balance=0):

self.owner = owner

self.__balance = balance  # 私有属性(以双下划线开头)

defdeposit(self, amount):

"""存款"""

if amount > 0:

self.__balance += amount

print(f"存入 ¥{amount},余额:¥{self.__balance}")

else:

print("存款金额必须大于 0")

defwithdraw(self, amount):

"""取款"""

if amount > self.__balance:

print("余额不足!")

elif amount > 0:

self.__balance -= amount

print(f"取出 ¥{amount},余额:¥{self.__balance}")

else:

print("取款金额必须大于 0")

defget_balance(self):

"""查看余额(提供安全的访问方式)"""

returnself.__balance

# 测试

account = BankAccount("张三", 1000)

account.deposit(500)

account.withdraw(300)

print(account.get_balance())  # 1200

# 尝试直接访问私有属性(Python 不是真正的私有,只是改名隐藏)

# print(account.__balance)  # AttributeError!

print(account._BankAccount__balance)  # 1200(不建议这样做)

```

### 3.2@property 装饰器

```python

classStudent:

"""学生类,带成绩验证"""

def__init__(self, name):

self.name = name

self.__score = 0

@property

defscore(self):

"""读取分数"""

returnself.__score

@score.setter

defscore(self, value):

"""设置分数(带验证)"""

if0 <= value <= 100:

self.__score = value

else:

raiseValueError("分数必须在 0-100 之间")

@property

defgrade(self):

"""根据分数自动计算等级"""

ifself.__score >= 90:

return"优秀"

elifself.__score >= 80:

return"良好"

elifself.__score >= 60:

return"及格"

else:

return"不及格"

# 测试

student = Student("李四")

student.score = 85

print(f"{student.name}的分数: {student.score},等级: {student.grade}")

# 李四的分数: 85,等级: 良好

student.score = 150# ValueError: 分数必须在 0-100 之间

```

---

## 四、继承——站在巨人的肩膀上

### 4.1 单继承

```python

# 基类(父类)

classAnimal:

def__init__(self, name, age):

self.name = name

self.age = age

defspeak(self):

return"我不知道发出什么声音..."

definfo(self):

returnf"{self.name},{self.age}岁"

# 派生类(子类)

classCat(Animal):

def__init__(self, name, age, color):

super().__init__(name, age)  # 调用父类的 __init__

self.color = color

defspeak(self):

return"喵喵喵~"

definfo(self):

# 扩展父类的方法

returnf"{super().info()},{self.color}"

# 测试

cat = Cat("咪咪", 3, "橘色")

print(cat.speak())    # 喵喵喵~

print(cat.info())     # 咪咪,3岁,橘色

```

### 4.2 方法重写与多态

```python

classAnimal:

def__init__(self, name):

self.name = name

defspeak(self):

raiseNotImplementedError("子类必须实现此方法")

def__str__(self):

returnf"动物: {self.name}"

classDog(Animal):

defspeak(self):

return"汪汪汪!"

classCat(Animal):

defspeak(self):

return"喵喵喵~"

classDuck(Animal):

defspeak(self):

return"嘎嘎嘎~"

# 多态:不同对象对同一方法做出不同响应

animals = [Dog("旺财"), Cat("咪咪"), Duck("嘎嘎")]

for animal in animals:

print(f"{animal}说: {animal.speak()}")

# 动物: 旺财说: 汪汪汪!

# 动物: 咪咪说: 喵喵喵~

# 动物: 嘎嘎说: 嘎嘎嘎~

```

### 4.3 多重继承

```python

classSwimmer:

defswim(self):

return"我会游泳!"

classFlyer:

deffly(self):

return"我会飞翔!"

classDuck(Swimmer, Flyer, Animal):

"""鸭子继承了三个父类的特性"""

pass

duck = Duck("唐老鸭")

print(duck.speak())  # 嘎嘎嘎~(来自Animal)

print(duck.swim())   # 我会游泳!(来自Swimmer)

print(duck.fly())    # 我会飞翔!(来自Flyer)

```

>**注意**:多重继承容易引起"菱形问题",Python 使用 MRO(Method Resolution Order)来解决。

> 用 `类名.__mro__` 可以查看方法的解析顺序。

---

## 五、魔术方法(Dunder Methods)

以双下划线开头和结尾的方法,Python 会自动调用它们。

### 5.1 常用魔术方法

```python

classRectangle:

"""矩形类"""

def__init__(self, width, height):

self.width = width

self.height = height

def__str__(self):

"""print() 调用的字符串表示"""

returnf"矩形({self.width} x {self.height})"

def__repr__(self):

"""开发者友好的字符串表示"""

returnf"Rectangle(width={self.width}, height={self.height})"

def__len__(self):

"""len() 调用的长度"""

returnint((self.width ** 2 + self.height ** 2) ** 0.5)  # 对角线长度

def__lt__(self, other):

"""小于比较(按面积)"""

returnself.area() < other.area()

def__le__(self, other):

"""小于等于"""

returnself.area() <= other.area()

def__eq__(self, other):

"""相等比较"""

ifnotisinstance(other, Rectangle):

returnNotImplemented

returnself.area() == other.area()

def__add__(self, other):

"""加法:两个矩形合并"""

return Rectangle(self.width + other.width, self.height + other.height)

defarea(self):

returnself.width * self.height

# 测试

rect1 = Rectangle(3, 4)

rect2 = Rectangle(5, 6)

rect3 = Rectangle(2, 7.5)

print(rect1)              # 矩形(3 x 4)

print(repr(rect2))        # Rectangle(width=5, height=6)

print(len(rect1))         # 5(对角线)

print(rect1 < rect2)      # True(面积 12 < 30)

print(rect2 == rect3)     # True(面积都是 30)

rect4 = rect1 + rect2

print(rect4)              # 矩形(8 x 10)

```

### 5.2 让类可迭代

```python

classFibonacci:

"""斐波那契数列生成器(支持迭代)"""

def__init__(self, count=10):

self.count = count

def__iter__(self):

self._a, self._b = 0, 1

self._index = 0

returnself

def__next__(self):

ifself._index >= self.count:

raiseStopIteration

self._index += 1

        result = self._a

self._a, self._b = self._b, self._a + self._b

return result

# 使用

fib = Fibonacci(10)

for num in fib:

print(num, end=" ")

# 0 1 1 2 3 5 8 13 21 34

```

---

## 六、类方法与静态方法

```python

classMathUtils:

PI = 3.1415926535

def__init__(self, radius):

self.radius = radius

# 实例方法(正常方法)

defarea(self):

return MathUtils.PI * self.radius ** 2

# 类方法:操作类属性,可以用类名直接调用

@classmethod

defset_pi(cls, value):

cls.PI = value

print(f"PI 已设置为 {value}")

# 静态方法:既不需要self也不需要cls,只是放在类里的工具函数

@staticmethod

defis_positive(number):

return number > 0

@staticmethod

defcircle_circumference(radius):

return2 * MathUtils.PI * radius

# 测试

utils = MathUtils(5)

print(utils.area())            # 78.53981633750001

print(MathUtils.circle_circumference(5))  # 31.415926535

MathUtils.set_pi(3.1416)

utils2 = MathUtils(10)

print(utils2.area())           # 314.16

print(MathUtils.is_positive(-5))   # False

print(MathUtils.is_positive(3))    # True

```

---

## 七、抽象类

```python

from abc importABC, abstractmethod

classShape(ABC):

"""图形抽象基类"""

@abstractmethod

defarea(self):

pass

@abstractmethod

defperimeter(self):

pass

defdescription(self):

returnf"这是一个{self.__class__.__name__}"

# 下面不实现area和perimeter会报错

classCircle(Shape):

def__init__(self, radius):

self.radius = radius

defarea(self):

return3.14159 * self.radius ** 2

defperimeter(self):

return2 * 3.14159 * self.radius

classSquare(Shape):

def__init__(self, side):

self.side = side

defarea(self):

returnself.side ** 2

defperimeter(self):

return4 * self.side

# 测试

circle = Circle(5)

square = Square(4)

print(circle.description())   # 这是一个Circle

print(f"圆面积: {circle.area():.2f}")

print(f"正方形周长: {square.perimeter()}")

# 不能实例化抽象类

# s = Shape()  # TypeError!

```

---

## 八、实战项目:简易银行账户系统

```python

from abc importABC, abstractmethod

from datetime import datetime

classAccount(ABC):

"""账户抽象基类"""

    _next_account_no = 1000

def__init__(self, owner, balance=0):

        Account._next_account_no += 1

self.account_no = Account._next_account_no

self.owner = owner

self.balance = balance

self.transactions = []

self._record_transaction(f"开户,初始余额: ¥{balance}")

def_record_transaction(self, description):

"""记录交易"""

        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

self.transactions.append({

"time": timestamp,

"description": description

        })

@abstractmethod

defwithdraw(self, amount):

pass

@abstractmethod

defdeposit(self, amount):

pass

defstatement(self):

"""生成账单"""

print(f"\n{'='*50}")

print(f"  账户持有人: {self.owner}")

print(f"  账号: {self.account_no}")

print(f"  当前余额: ¥{self.balance:.2f}")

print(f"{'='*50}")

print("  交易记录:")

for txn inself.transactions:

print(f"    [{txn['time']}] {txn['description']}")

print()

classSavingsAccount(Account):

"""储蓄账户"""

def__init__(self, owner, balance=0, interest_rate=0.03):

super().__init__(owner, balance)

self.interest_rate = interest_rate

defdeposit(self, amount):

if amount > 0:

self.balance += amount

self._record_transaction(f"存款 ¥{amount:.2f}")

print(f"✅ 成功存入 ¥{amount:.2f}")

else:

print("❌ 存款金额必须大于 0")

defwithdraw(self, amount):

if amount > 0:

if amount <= self.balance:

self.balance -= amount

self._record_transaction(f"取款 ¥{amount:.2f}")

print(f"✅ 成功取出 ¥{amount:.2f}")

else:

print("❌ 余额不足!")

else:

print("❌ 取款金额必须大于 0")

defadd_interest(self):

"""计算利息"""

        interest = self.balance * self.interest_rate

self.balance += interest

self._record_transaction(f"利息 ¥{interest:.2f}")

print(f"🏦 利息 ¥{interest:.2f} 已入账")

classCheckingAccount(Account):

"""支票账户(允许透支)"""

OVERDRAFT_LIMIT = 5000

defdeposit(self, amount):

if amount > 0:

self.balance += amount

self._record_transaction(f"存款 ¥{amount:.2f}")

print(f"✅ 成功存入 ¥{amount:.2f}")

defwithdraw(self, amount):

if amount > 0:

if amount <= self.balance + self.OVERDRAFT_LIMIT:

self.balance -= amount

self._record_transaction(f"取款 ¥{amount:.2f}")

ifself.balance < 0:

print(f"⚠️ 成功取出 ¥{amount:.2f},当前已透支 ¥{abs(self.balance):.2f}")

else:

print(f"✅ 成功取出 ¥{amount:.2f}")

else:

print(f"❌ 超出透支限额!最大可透支 ¥{self.OVERDRAFT_LIMIT}")

else:

print("❌ 取款金额必须大于 0")

# ============ 演示 ============

print("🏦 创建储蓄账户...")

savings = SavingsAccount("张三", 10000, 0.05)

savings.deposit(5000)

savings.withdraw(3000)

print("\n🏦 创建支票账户...")

checking = CheckingAccount("李四", 2000)

checking.deposit(10000)

checking.withdraw(15000)  # 允许透支

print("\n📋 查看储蓄账户账单...")

savings.statement()

print("\n📋 查看支票账户账单...")

checking.statement()

```

运行效果:

```

🏦 创建储蓄账户...

✅ 成功存入 ¥5000.00

✅ 成功取出 ¥3000.00

🏦 创建支票账户...

✅ 成功存入 ¥10000.00

⚠️ 成功取出 ¥15000.00,当前已透支 ¥5000.00

📋 查看储蓄账户账单...

==================================================

  账户持有人: 张三

  账号: 1002

  当前余额: ¥12000.00

==================================================

  交易记录:

    [2026-07-02 14:00:00] 开户,初始余额: ¥10000

    [2026-07-02 14:00:00] 存款 ¥5000.00

    [2026-07-02 14:00:00] 取款 ¥3000.00

```

---

## 九、OOP 核心原则回顾

### 三大支柱

| 原则 | 说明 | 本课对应 |

|------|------|---------|

| **封装** | 隐藏内部实现,对外暴露安全接口 | `__balance`、`@property` |

| **继承** | 子类继承父类的属性和方法 | `class Dog(Animal)` |

| **多态** | 不同对象对同一消息有不同反应 | 不同动物调用 `speak()` |

### 额外补充:抽象

-**抽象基类**(`ABC`)定义接口规范

- 子类必须实现抽象方法

- 保证接口的一致性

---

## 十、练习题

### 练习 1:学生成绩管理类

```python

classStudent:

def__init__(self, name):

self.name = name

self.scores = {}

defadd_score(self, subject, score):

if0 <= score <= 100:

self.scores[subject] = score

defaverage(self):

ifnotself.scores:

return0

returnsum(self.scores.values()) / len(self.scores)

defgrade(self):

        avg = self.average()

if avg >= 90: return"A"

elif avg >= 80: return"B"

elif avg >= 70: return"C"

elif avg >= 60: return"D"

else: return"F"

stu = Student("王五")

stu.add_score("数学", 95)

stu.add_score("英语", 87)

print(f"平均分: {stu.average():.1f}, 等级: {stu.grade()}")

```

### 练习 2:链表节点

```python

classNode:

def__init__(self, data):

self.data = data

self.next = None

classLinkedList:

def__init__(self):

self.head = None

defappend(self, data):

        new_node = Node(data)

ifnotself.head:

self.head = new_node

return

        current = self.head

while current.next:

            current = current.next

        current.next = new_node

defdisplay(self):

        nodes = []

        current = self.head

while current:

            nodes.append(str(current.data))

            current = current.next

print(" -> ".join(nodes) + " -> None")

ll = LinkedList()

ll.append(10)

ll.append(20)

ll.append(30)

ll.display()  # 10 -> 20 -> 30 -> None

```

### 练习 3:继承层次设计

设计一个图形库,包含:

-`Shape`(抽象基类)

-`Circle`、`Rectangle`、`Triangle`(子类)

- 每个子类实现 `area()` 和 `perimeter()` 方法

- 测试各种图形的面积和周长

### 练习 4:宠物店模拟器

```python

classPet:

def__init__(self, name, species):

self.name = name

self.species = species

self.hunger = 50

self.happiness = 50

deffeed(self):

self.hunger -= 20

self.happiness += 10

print(f"{self.name} 吃了东西!饥饿: {self.hunger}, 快乐: {self.happiness}")

defplay(self):

self.happiness += 30

self.hunger += 10

print(f"{self.name} 玩了玩具!饥饿: {self.hunger}, 快乐: {self.happiness}")

pet = Pet("豆豆", "狗狗")

pet.feed()

pet.play()

```

### 练习 5:图书馆管理系统

```python

classBook:

def__init__(self, title, author, isbn):

self.title = title

self.author = author

self.isbn = isbn

self.is_borrowed = False

classLibrary:

def__init__(self):

self.books = []

defadd_book(self, book):

self.books.append(book)

print(f"📚 添加了《{book.title}》")

defborrow_book(self, isbn):

for book inself.books:

if book.isbn == isbn:

if book.is_borrowed:

print("此书已被借出")

else:

                    book.is_borrowed = True

print(f"✅ 借走了《{book.title}》")

return

print("❌ 未找到该书")

defreturn_book(self, isbn):

for book inself.books:

if book.isbn == isbn:

                book.is_borrowed = False

print(f"📖 归还了《{book.title}》")

return

print("❌ 未找到该书")

lib = Library()

lib.add_book(Book("Python编程", "作者A", "978-7"))

lib.borrow_book("978-7")

lib.return_book("978-7")

```

---

## 下期预告

**Python 教程 Episode 04 — 装饰器、生成器与文件IO**

- 装饰器:在不修改原函数的前提下扩展功能(带参数的装饰器、@functools.wraps)

- 生成器:yield 的工作原理,内存高效的无限序列

- 文件读写:open() 的几种模式、with 语句、CSV/JSON 处理

- 异常处理:try-except-else-finally 完整结构

- 实战:用装饰器实现函数计时器和用生成器处理大文件

---

*如果觉得本系列对你有帮助,欢迎点赞、评论、转发!有任何问题,在留言区讨论。*

最新文章

随机文章