9Python编程:从入门到实践(第3版)

类

面向对象编程

类对象继承多态

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第9章:类(Classes)

一、导读

1.1 本章学习目标

第9章介绍Python的面向对象编程。本章核心目标:

  • 掌握类的定义和对象的创建:class关键字
  • 理解__init__方法和self参数
  • 学会继承和方法重写
  • 掌握特殊方法:__str__、__repr__、__eq__等
  • 理解类属性和实例属性的区别

1.2 为什么本章如此重要

面向对象编程是组织大型代码的有效方式。Python的OOP语法简洁直观,是学习面向对象思想的理想语言。理解类的设计原则,才能编写出结构清晰的代码。

1.3 核心问题引导

self参数是什么?为什么需要它?

Python的继承和Java/C++有什么不同?

什么是鸭子类型?

类方法和静态方法有什么区别?


二、核心概念详解

9.1 类的基础

python
class Dog:
    """表示狗的类"""
    
    # 类属性
    species = "Canis familiaris"
    
    def __init__(self, name, age):
        """初始化属性"""
        self.name = name  # 实例属性
        self.age = age
    
    def sit(self):
        """模拟狗坐下"""
        print(f"{self.name} is now sitting.")
    
    def roll_over(self):
        """模拟狗打滚"""
        print(f"{self.name} rolled over!")
    
    def __str__(self):
        return f"{self.name} ({self.age} years old)"
    
    def __repr__(self):
        return f"Dog('{self.name}', {self.age})"

# 创建对象
my_dog = Dog("Buddy", 3)
print(my_dog.name)     # Buddy
my_dog.sit()           # Buddy is now sitting.
print(my_dog)          # Buddy (3 years old)

9.2 继承

python
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        pass  # 抽象方法
    
    def __str__(self):
        return self.name

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

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

# 多态
animals = [Dog("Buddy"), Cat("Whiskers"), Dog("Max")]
for animal in animals:
    print(animal.speak())

# super()调用父类方法
class Puppy(Dog):
    def __init__(self, name, age, trick_count=0):
        super().__init__(name, age)
        self.trick_count = trick_count
    
    def learn_trick(self):
        self.trick_count += 1
        print(f"{self.name} learned a new trick! ({self.trick_count} total)")

puppy = Puppy("Rex", 1)
puppy.sit()         # 继承自Dog
puppy.learn_trick() # Puppy自己的方法

9.3 特殊方法

python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __str__(self):
        return f"({self.x}, {self.y})"
    
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)
    
    def __sub__(self, other):
        return Point(self.x - other.x, self.y - other.y)
    
    def __abs__(self):
        return (self.x**2 + self.y**2) ** 0.5
    
    def __lt__(self, other):
        return abs(self) < abs(other)

p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1 + p2)    # (4, 6)
print(abs(p2))    # 5.0
print(p1 < p2)    # True

9.4 类方法和静态方法

python
class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day
    
    @classmethod
    def from_string(cls, date_str):
        """工厂方法"""
        year, month, day = map(int, date_str.split('-'))
        return cls(year, month, day)
    
    @staticmethod
    def is_valid(date_str):
        """验证日期格式"""
        try:
            parts = date_str.split('-')
            return len(parts) == 3 and all(p.isdigit() for p in parts)
        except:
            return False
    
    def __str__(self):
        return f"{self.year}-{self.month:02d}-{self.day:02d}"

# 使用类方法
d = Date.from_string("2024-01-15")
print(d)

# 使用静态方法
print(Date.is_valid("2024-01-15"))

9.5 属性装饰器

python
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("Temperature below absolute zero!")
        self._celsius = value
    
    @property
    def fahrenheit(self):
        return self._celsius * 9/5 + 32
    
    @fahrenheit.setter
    def fahrenheit(self, value):
        self.celsius = (value - 32) * 5/9

temp = Temperature(25)
print(temp.celsius)       # 25
print(temp.fahrenheit)    # 77.0
temp.fahrenheit = 100
print(temp.celsius)       # 37.78

三、实战案例

3.1 银行账户系统

python
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self._balance = balance
        self._transactions = []
    
    @property
    def balance(self):
        return self._balance
    
    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("Deposit amount must be positive")
        self._balance += amount
        self._transactions.append(('deposit', amount))
    
    def withdraw(self, amount):
        if amount <= 0:
            raise ValueError("Withdraw amount must be positive")
        if amount > self._balance:
            raise ValueError("Insufficient funds")
        self._balance -= amount
        self._transactions.append(('withdraw', amount))
    
    def get_history(self):
        return self._transactions
    
    def __str__(self):
        return f"{self.owner}: ${self.balance:.2f}"

class SavingsAccount(BankAccount):
    def __init__(self, owner, balance=0, interest_rate=0.01):
        super().__init__(owner, balance)
        self.interest_rate = interest_rate
    
    def apply_interest(self):
        interest = self._balance * self.interest_rate
        self.deposit(interest)

# 使用
acc = SavingsAccount("Alice", 1000, 0.05)
acc.deposit(500)
acc.withdraw(200)
acc.apply_interest()
print(acc)
print(acc.get_history())

四、本章小结

第9章介绍了Python的面向对象编程:类的定义、__init__和self、继承、特殊方法、类方法/静态方法、属性装饰器。Python的OOP简洁而强大。


五、思考与练习

思考题

Python没有私有成员,如何模拟私有属性?

什么是鸭子类型?和接口有什么关系?

__str__和__repr__有什么区别?

多继承的MRO(方法解析顺序)是什么?

编程练习

实现一个Fraction类,支持分数运算。

实现一个简单的卡牌游戏(使用类)。

使用继承实现一个图形类层次结构。


9/11类
0%