Skip to content

面向对象编程

面向对象编程(Object-Oriented Programming,简称OOP)是一种程序设计范式。Python是一种支持面向对象编程的语言,它提供了类(Class)和对象(Object)的概念,以及封装、继承、多态等特性。本章将详细介绍Python中的面向对象编程。

面向对象基础概念

什么是面向对象

面向对象编程是一种将程序组织为对象集合的编程方式。每个对象都包含数据(属性)和操作数据的方法。

python
# 面向对象 vs 面向过程

# 面向过程的方式
student_name = "张三"
student_age = 20
student_score = 85

def print_student_info(name, age, score):
    print(f"姓名: {name}, 年龄: {age}, 成绩: {score}")

def update_score(score, new_score):
    return new_score

print_student_info(student_name, student_age, student_score)

# 面向对象的方式
class Student:
    def __init__(self, name, age, score):
        self.name = name      # 属性
        self.age = age        # 属性
        self.score = score    # 属性
    
    def print_info(self):     # 方法
        print(f"姓名: {self.name}, 年龄: {self.age}, 成绩: {self.score}")
    
    def update_score(self, new_score):  # 方法
        self.score = new_score

# 创建对象
student = Student("张三", 20, 85)
student.print_info()
student.update_score(90)
student.print_info()

类与对象

python
# 类的定义和对象的创建

# 定义一个简单的类
class Person:
    """这是一个表示人的类"""  # 类的文档字符串
    
    # 类属性(所有实例共享)
    species = "人类"
    
    # 构造方法(初始化方法)
    def __init__(self, name, age):
        # 实例属性(每个实例独有)
        self.name = name
        self.age = age
    
    # 实例方法
    def say_hello(self):
        print(f"大家好,我是{self.name},今年{self.age}岁")
    
    # 实例方法
    def have_birthday(self):
        self.age += 1
        print(f"{self.name}过生日了,现在{self.age}岁")

# 创建对象(实例化)
person1 = Person("张三", 20)
person2 = Person("李四", 25)

# 访问属性
print(f"person1的名字: {person1.name}")
print(f"person2的年龄: {person2.age}")

# 访问类属性
print(f"person1的物种: {person1.species}")
print(f"person2的物种: {person2.species}")

# 调用方法
person1.say_hello()
person2.say_hello()

# 修改属性
person1.have_birthday()

# 查看对象的类型
print(f"person1的类型: {type(person1)}")
print(f"person1是Person的实例: {isinstance(person1, Person)}")

类的属性

实例属性与类属性

python
# 实例属性与类属性的区别

class Student:
    # 类属性:所有实例共享
    school = "清华大学"
    count = 0  # 统计学生数量
    
    def __init__(self, name, age):
        # 实例属性:每个实例独有
        self.name = name
        self.age = age
        # 每创建一个实例,计数加1
        Student.count += 1
    
    def info(self):
        print(f"姓名: {self.name}, 年龄: {self.age}, 学校: {self.school}")

# 创建实例
s1 = Student("张三", 20)
s2 = Student("李四", 21)

# 访问实例属性
print(f"s1.name: {s1.name}")  # 张三
print(f"s2.name: {s2.name}")  # 李四

# 访问类属性
print(f"s1.school: {s1.school}")  # 清华大学
print(f"s2.school: {s2.school}")  # 清华大学
print(f"Student.count: {Student.count}")  # 2

# 修改类属性(影响所有实例)
Student.school = "北京大学"
print(f"修改后 s1.school: {s1.school}")  # 北京大学
print(f"修改后 s2.school: {s2.school}")  # 北京大学

# 通过实例修改类属性(实际上创建了新的实例属性)
s1.school = "复旦大学"  # 这会创建一个新的实例属性
print(f"s1.school: {s1.school}")  # 复旦大学(实例属性)
print(f"s2.school: {s2.school}")  # 北京大学(类属性)
print(f"Student.school: {Student.school}")  # 北京大学

# 删除实例属性后,会访问类属性
del s1.school
print(f"删除后 s1.school: {s1.school}")  # 北京大学(类属性)

属性的访问控制

python
# 属性的访问控制

class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner           # 公有属性
        self._balance = balance      # 保护属性(约定,单下划线)
        self.__password = "123456"   # 私有属性(双下划线,名称修饰)
    
    def deposit(self, amount):
        """存款"""
        if amount > 0:
            self._balance += amount
            print(f"存入{amount}元,余额: {self._balance}元")
    
    def withdraw(self, amount, password):
        """取款"""
        if password != self.__password:
            print("密码错误!")
            return
        if amount > self._balance:
            print("余额不足!")
            return
        self._balance -= amount
        print(f"取出{amount}元,余额: {self._balance}元")
    
    def get_balance(self):
        """获取余额"""
        return self._balance
    
    def change_password(self, old_pwd, new_pwd):
        """修改密码"""
        if old_pwd == self.__password:
            self.__password = new_pwd
            print("密码修改成功!")
        else:
            print("原密码错误!")

# 创建账户
account = BankAccount("张三", 1000)

# 访问公有属性
print(f"账户持有人: {account.owner}")

# 访问保护属性(可以访问,但不推荐)
print(f"余额: {account._balance}")  # 可以访问,但约定不直接访问

# 访问私有属性(无法直接访问)
# print(account.__password)  # AttributeError

# 通过名称修饰访问私有属性(不推荐)
print(f"私有属性: {account._BankAccount__password}")  # 可以访问

# 通过方法访问
account.deposit(500)
account.withdraw(200, "123456")
account.withdraw(200, "wrong")  # 密码错误
print(f"当前余额: {account.get_balance()}元")

使用 property 装饰器

python
# 使用 property 装饰器实现属性访问控制

class Circle:
    def __init__(self, radius):
        self._radius = radius
    
    @property
    def radius(self):
        """获取半径"""
        print("获取半径")
        return self._radius
    
    @radius.setter
    def radius(self, value):
        """设置半径"""
        print("设置半径")
        if value <= 0:
            raise ValueError("半径必须为正数")
        self._radius = value
    
    @radius.deleter
    def radius(self):
        """删除半径"""
        print("删除半径")
        del self._radius
    
    @property
    def area(self):
        """计算面积(只读属性)"""
        import math
        return math.pi * self._radius ** 2
    
    @property
    def circumference(self):
        """计算周长(只读属性)"""
        import math
        return 2 * math.pi * self._radius

# 创建圆
circle = Circle(5)

# 获取半径
print(f"半径: {circle.radius}")

# 设置半径
circle.radius = 10
print(f"新半径: {circle.radius}")

# 尝试设置无效值
try:
    circle.radius = -5
except ValueError as e:
    print(f"错误: {e}")

# 访问只读属性
print(f"面积: {circle.area:.2f}")
print(f"周长: {circle.circumference:.2f}")

# 只读属性不能设置
# circle.area = 100  # AttributeError

# 删除属性
del circle.radius
# circle.radius  # AttributeError

类的方法

实例方法、类方法和静态方法

python
# 实例方法、类方法和静态方法

class Employee:
    # 类属性
    company = "科技公司"
    count = 0
    
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.count += 1
    
    # 实例方法:第一个参数是 self
    def get_info(self):
        """获取员工信息"""
        return f"姓名: {self.name}, 薪资: {self.salary}, 公司: {self.company}"
    
    def raise_salary(self, amount):
        """涨薪"""
        self.salary += amount
        print(f"{self.name}涨薪{amount}元,新薪资: {self.salary}元")
    
    # 类方法:第一个参数是 cls
    @classmethod
    def get_company(cls):
        """获取公司名称"""
        return cls.company
    
    @classmethod
    def set_company(cls, new_name):
        """设置公司名称"""
        cls.company = new_name
        print(f"公司名称已更改为: {cls.company}")
    
    @classmethod
    def from_string(cls, emp_str):
        """从字符串创建员工(工厂方法)"""
        name, salary = emp_str.split("-")
        return cls(name, int(salary))
    
    # 静态方法:不需要 self 或 cls
    @staticmethod
    def is_workday(date):
        """判断是否是工作日"""
        from datetime import date as d
        if isinstance(date, str):
            # 简单示例,假设输入格式为 "2024-01-15"
            year, month, day = map(int, date.split("-"))
            date = d(year, month, day)
        
        # 周六(5)和周日(6)不是工作日
        return date.weekday() < 5
    
    @staticmethod
    def calculate_tax(salary, rate=0.1):
        """计算税费"""
        return salary * rate

# 创建员工
emp1 = Employee("张三", 10000)
emp2 = Employee("李四", 12000)

# 调用实例方法
print(emp1.get_info())
emp1.raise_salary(1000)

# 调用类方法
print(f"公司: {Employee.get_company()}")
Employee.set_company("创新科技")
print(f"新公司名: {emp1.get_company()}")

# 使用类方法创建实例
emp3 = Employee.from_string("王五-15000")
print(emp3.get_info())

# 调用静态方法
print(f"2024-01-15是工作日: {Employee.is_workday('2024-01-15')}")
print(f"税费: {Employee.calculate_tax(10000)}元")

# 静态方法也可以通过实例调用
print(f"税费: {emp1.calculate_tax(emp1.salary)}元")

# 打印员工总数
print(f"员工总数: {Employee.count}")

特殊方法(魔术方法)

python
# 常用特殊方法

class Point:
    """表示二维点的类"""
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    # __str__: 定义 print() 和 str() 的输出
    def __str__(self):
        return f"Point({self.x}, {self.y})"
    
    # __repr__: 定义 repr() 的输出,应该返回可以重建对象的表达式
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
    
    # __eq__: 定义 == 运算符
    def __eq__(self, other):
        if not isinstance(other, Point):
            return False
        return self.x == other.x and self.y == other.y
    
    # __add__: 定义 + 运算符
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)
    
    # __sub__: 定义 - 运算符
    def __sub__(self, other):
        return Point(self.x - other.x, self.y - other.y)
    
    # __mul__: 定义 * 运算符
    def __mul__(self, scalar):
        return Point(self.x * scalar, self.y * scalar)
    
    # __len__: 定义 len() 函数
    def __len__(self):
        return 2  # 返回维度
    
    # __getitem__: 定义索引访问
    def __getitem__(self, index):
        if index == 0:
            return self.x
        elif index == 1:
            return self.y
        raise IndexError("Point index out of range")
    
    # __setitem__: 定义索引赋值
    def __setitem__(self, index, value):
        if index == 0:
            self.x = value
        elif index == 1:
            self.y = value
        else:
            raise IndexError("Point index out of range")
    
    # __contains__: 定义 in 运算符
    def __contains__(self, value):
        return value == self.x or value == self.y
    
    # __bool__: 定义 bool() 函数
    def __bool__(self):
        return self.x != 0 or self.y != 0
    
    # __abs__: 定义 abs() 函数
    def __abs__(self):
        import math
        return math.sqrt(self.x ** 2 + self.y ** 2)

# 使用特殊方法
p1 = Point(3, 4)
p2 = Point(1, 2)

print(f"p1: {p1}")  # __str__
print(f"repr(p1): {repr(p1)}")  # __repr__

print(f"p1 == p2: {p1 == p2}")  # __eq__
print(f"p1 + p2: {p1 + p2}")    # __add__
print(f"p1 - p2: {p1 - p2}")    # __sub__
print(f"p1 * 2: {p1 * 2}")      # __mul__

print(f"len(p1): {len(p1)}")    # __len__
print(f"p1[0]: {p1[0]}")        # __getitem__
p1[0] = 5                       # __setitem__
print(f"修改后 p1: {p1}")

print(f"3 in p1: {3 in p1}")    # __contains__
print(f"bool(p1): {bool(p1)}")  # __bool__
print(f"abs(p1): {abs(p1)}")    # __abs__

继承

基本继承

python
# 基本继承

# 父类(基类)
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def eat(self):
        print(f"{self.name}正在吃东西")
    
    def sleep(self):
        print(f"{self.name}正在睡觉")
    
    def make_sound(self):
        print(f"{self.name}发出声音")

# 子类(派生类)
class Dog(Animal):
    def __init__(self, name, age, breed):
        # 调用父类的构造方法
        super().__init__(name, age)
        self.breed = breed  # 子类特有的属性
    
    # 重写父类方法
    def make_sound(self):
        print(f"{self.name}汪汪叫")
    
    # 子类特有的方法
    def fetch(self):
        print(f"{self.name}正在捡球")

# 另一个子类
class Cat(Animal):
    def __init__(self, name, age, color):
        super().__init__(name, age)
        self.color = color
    
    def make_sound(self):
        print(f"{self.name}喵喵叫")
    
    def climb(self):
        print(f"{self.name}正在爬树")

# 创建实例
dog = Dog("旺财", 3, "金毛")
cat = Cat("咪咪", 2, "白色")

# 调用继承的方法
dog.eat()
cat.sleep()

# 调用重写的方法
dog.make_sound()
cat.make_sound()

# 调用子类特有的方法
dog.fetch()
cat.climb()

# 访问子类特有的属性
print(f"{dog.name}{dog.breed}")
print(f"{cat.name}{cat.color}的")

# 检查继承关系
print(f"dog是Dog的实例: {isinstance(dog, Dog)}")
print(f"dog是Animal的实例: {isinstance(dog, Animal)}")
print(f"Dog是Animal的子类: {issubclass(Dog, Animal)}")

多重继承

python
# 多重继承

class Flyable:
    """会飞的"""
    def fly(self):
        print(f"{self.name}正在飞翔")

class Swimmable:
    """会游泳的"""
    def swim(self):
        print(f"{self.name}正在游泳")

class Walkable:
    """会走的"""
    def walk(self):
        print(f"{self.name}正在走路")

# 多重继承
class Duck(Animal, Flyable, Swimmable, Walkable):
    def __init__(self, name, age):
        super().__init__(name, age)
    
    def make_sound(self):
        print(f"{self.name}嘎嘎叫")

# 创建鸭子
duck = Duck("唐老鸭", 5)

# 调用各种方法
duck.make_sound()  # 自己的方法
duck.eat()         # 继承自 Animal
duck.fly()         # 继承自 Flyable
duck.swim()        # 继承自 Swimmable
duck.walk()        # 继承自 Walkable

# 方法解析顺序(MRO)
print(f"\nDuck的MRO: {Duck.__mro__}")

# 菱形继承问题
class A:
    def method(self):
        print("A.method")

class B(A):
    def method(self):
        print("B.method")
        super().method()

class C(A):
    def method(self):
        print("C.method")
        super().method()

class D(B, C):
    def method(self):
        print("D.method")
        super().method()

# 创建实例并调用方法
d = D()
d.method()
# 输出顺序: D.method -> B.method -> C.method -> A.method
# Python使用C3线性化算法解决菱形继承问题

抽象类

python
# 抽象类

from abc import ABC, abstractmethod

# 定义抽象类
class Shape(ABC):
    """形状抽象类"""
    
    @abstractmethod
    def area(self):
        """计算面积(抽象方法)"""
        pass
    
    @abstractmethod
    def perimeter(self):
        """计算周长(抽象方法)"""
        pass
    
    # 具体方法
    def info(self):
        return f"面积: {self.area()}, 周长: {self.perimeter()}"

# 具体子类
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)

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        import math
        return math.pi * self.radius ** 2
    
    def perimeter(self):
        import math
        return 2 * math.pi * self.radius

# 不能实例化抽象类
# shape = Shape()  # TypeError

# 实例化具体子类
rect = Rectangle(4, 5)
circle = Circle(3)

print(f"矩形: {rect.info()}")
print(f"圆形: {circle.info()}")

# 使用抽象类作为类型提示
shapes = [rect, circle]
for shape in shapes:
    print(f"类型: {type(shape).__name__}, {shape.info()}")

多态

多态的实现

python
# 多态:同一操作作用于不同对象,产生不同的结果

class Animal:
    def make_sound(self):
        pass

class Dog(Animal):
    def make_sound(self):
        return "汪汪汪"

class Cat(Animal):
    def make_sound(self):
        return "喵喵喵"

class Cow(Animal):
    def make_sound(self):
        return "哞哞哞"

# 多态函数
def animal_sound(animal):
    """接受任何 Animal 类型的对象"""
    print(f"动物叫声: {animal.make_sound()}")

# 多态的应用
animals = [Dog(), Cat(), Cow()]

for animal in animals:
    animal_sound(animal)

# 另一个多态示例:文件处理
class FileHandler:
    def read(self):
        pass
    
    def write(self, content):
        pass

class TextFileHandler(FileHandler):
    def __init__(self, filename):
        self.filename = filename
    
    def read(self):
        with open(self.filename, 'r', encoding='utf-8') as f:
            return f.read()
    
    def write(self, content):
        with open(self.filename, 'w', encoding='utf-8') as f:
            f.write(content)

class JsonFileHandler(FileHandler):
    def __init__(self, filename):
        self.filename = filename
    
    def read(self):
        import json
        with open(self.filename, 'r', encoding='utf-8') as f:
            return json.load(f)
    
    def write(self, content):
        import json
        with open(self.filename, 'w', encoding='utf-8') as f:
            json.dump(content, f, ensure_ascii=False, indent=2)

# 多态使用
def process_file(handler, content=None):
    """处理文件的通用函数"""
    if content:
        handler.write(content)
        print(f"写入成功: {handler.filename}")
    data = handler.read()
    print(f"读取内容: {data}")
    return data

鸭子类型

python
# 鸭子类型(Duck Typing)
# "如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子"

class Duck:
    def quack(self):
        print("嘎嘎嘎")
    
    def walk(self):
        print("摇摇摆摆地走")

class Person:
    def quack(self):
        print("人在模仿鸭子叫")
    
    def walk(self):
        print("人在模仿鸭子走")

class Robot:
    def quack(self):
        print("机器人发出嘎嘎声")
    
    def walk(self):
        print("机器人移动")

# 鸭子类型函数
def make_it_quack_and_walk(thing):
    """不关心对象的具体类型,只关心它是否有这些方法"""
    thing.quack()
    thing.walk()

# 使用
duck = Duck()
person = Person()
robot = Robot()

print("=== 真正的鸭子 ===")
make_it_quack_and_walk(duck)

print("\n=== 人模仿鸭子 ===")
make_it_quack_and_walk(person)

print("\n=== 机器人 ===")
make_it_quack_and_walk(robot)

# 鸭子类型的实际应用:迭代器协议
class Countdown:
    """倒计时迭代器"""
    def __init__(self, start):
        self.start = start
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.start <= 0:
            raise StopIteration
        self.start -= 1
        return self.start + 1

# 使用自定义迭代器
print("\n=== 倒计时 ===")
for num in Countdown(5):
    print(num, end=" ")
print()

# 可以在任何需要迭代器的地方使用
print(list(Countdown(3)))

封装

封装的实现

python
# 封装:隐藏内部实现细节,只暴露必要的接口

class BankAccount:
    """银行账户类"""
    
    def __init__(self, owner, initial_balance=0):
        self.owner = owner
        self.__balance = initial_balance  # 私有属性
        self.__transaction_history = []    # 私有属性
    
    def deposit(self, amount):
        """存款"""
        if amount <= 0:
            raise ValueError("存款金额必须大于0")
        self.__balance += amount
        self.__add_transaction("存款", amount)
        return f"存款成功,当前余额: {self.__balance}元"
    
    def withdraw(self, amount):
        """取款"""
        if amount <= 0:
            raise ValueError("取款金额必须大于0")
        if amount > self.__balance:
            raise ValueError("余额不足")
        self.__balance -= amount
        self.__add_transaction("取款", amount)
        return f"取款成功,当前余额: {self.__balance}元"
    
    def get_balance(self):
        """查询余额"""
        return self.__balance
    
    def get_transaction_history(self):
        """获取交易历史"""
        return self.__transaction_history.copy()  # 返回副本,防止外部修改
    
    def __add_transaction(self, trans_type, amount):
        """添加交易记录(私有方法)"""
        from datetime import datetime
        transaction = {
            "type": trans_type,
            "amount": amount,
            "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "balance": self.__balance
        }
        self.__transaction_history.append(transaction)
    
    def transfer(self, other_account, amount):
        """转账"""
        # 使用公开方法进行操作
        self.withdraw(amount)
        other_account.deposit(amount)
        return f"转账成功: {self.owner} -> {other_account.owner}, {amount}元"

# 使用封装好的类
account1 = BankAccount("张三", 1000)
account2 = BankAccount("李四", 500)

# 通过公开方法操作
print(account1.deposit(500))
print(account1.withdraw(200))
print(account1.transfer(account2, 300))

# 查询余额
print(f"张三余额: {account1.get_balance()}元")
print(f"李四余额: {account2.get_balance()}元")

# 查看交易历史
print("\n张三的交易记录:")
for record in account1.get_transaction_history():
    print(f"  {record}")

组合与聚合

python
# 组合与聚合

# 组合:整体与部分的生命周期一致
class Engine:
    """发动机"""
    def __init__(self, horsepower):
        self.horsepower = horsepower
    
    def start(self):
        print(f"发动机启动,马力: {self.horsepower}")
    
    def stop(self):
        print("发动机停止")

class Wheel:
    """车轮"""
    def __init__(self, size):
        self.size = size
    
    def rotate(self):
        print(f"车轮转动,尺寸: {self.size}")

class Car:
    """汽车(组合关系)"""
    def __init__(self, brand, horsepower, wheel_size):
        self.brand = brand
        # 组合:Car 创建时同时创建 Engine 和 Wheel
        self.engine = Engine(horsepower)
        self.wheels = [Wheel(wheel_size) for _ in range(4)]
    
    def start(self):
        print(f"{self.brand}汽车启动")
        self.engine.start()
        for wheel in self.wheels:
            wheel.rotate()
    
    def stop(self):
        self.engine.stop()
        print(f"{self.brand}汽车停止")

# 聚合:整体与部分的生命周期独立
class Student:
    """学生"""
    def __init__(self, name, student_id):
        self.name = name
        self.student_id = student_id
    
    def study(self):
        print(f"{self.name}正在学习")

class Classroom:
    """教室(聚合关系)"""
    def __init__(self, room_number):
        self.room_number = room_number
        self.students = []  # 学生列表
    
    def add_student(self, student):
        """添加学生"""
        self.students.append(student)
        print(f"{student.name}加入{self.room_number}教室")
    
    def remove_student(self, student):
        """移除学生"""
        if student in self.students:
            self.students.remove(student)
            print(f"{student.name}离开{self.room_number}教室")
    
    def show_students(self):
        """显示所有学生"""
        print(f"{self.room_number}教室的学生:")
        for student in self.students:
            print(f"  - {student.name} ({student.student_id})")

# 使用组合
car = Car("丰田", 200, 18)
car.start()
car.stop()

print()

# 使用聚合
student1 = Student("张三", "001")
student2 = Student("李四", "002")

classroom = Classroom("A101")
classroom.add_student(student1)
classroom.add_student(student2)
classroom.show_students()

# 学生可以独立存在
student1.study()

数据类

python
# 数据类(Python 3.7+)

from dataclasses import dataclass, field
from typing import List

# 基本数据类
@dataclass
class Person:
    name: str
    age: int
    city: str = "北京"  # 默认值

# 创建实例
p1 = Person("张三", 25)
p2 = Person("李四", 30, "上海")
p3 = Person("张三", 25)  # 与 p1 相同

print(f"p1: {p1}")
print(f"p2: {p2}")
print(f"p1 == p3: {p1 == p3}")  # 自动实现 __eq__

# 更多选项
@dataclass(frozen=True)  # 不可变
class Point:
    x: float
    y: float

point = Point(3.0, 4.0)
print(f"Point: {point}")
# point.x = 5.0  # FrozenInstanceError

# 带默认工厂的数据类
@dataclass
class Student:
    name: str
    scores: List[int] = field(default_factory=list)
    grade: str = field(default="未评定", repr=False)  # 不显示在 repr 中
    
    def add_score(self, score):
        self.scores.append(score)
    
    def calculate_average(self):
        if not self.scores:
            return 0
        return sum(self.scores) / len(self.scores)

student = Student("张三")
student.add_score(85)
student.add_score(90)
student.add_score(78)
print(f"学生: {student}")
print(f"平均分: {student.calculate_average():.1f}")

# 继承数据类
@dataclass
class Employee(Person):
    department: str
    salary: float = 0.0

emp = Employee("王五", 28, "深圳", "技术部", 15000)
print(f"员工: {emp}")

小结

本章学习了Python面向对象编程的核心概念:

类与对象

  • 使用 class 关键字定义类
  • 使用 __init__ 方法初始化对象
  • 区分实例属性和类属性

封装

  • 使用 ___ 控制属性访问
  • 使用 @property 装饰器实现属性访问控制

继承

  • 单继承和多继承
  • 使用 super() 调用父类方法
  • 抽象类和抽象方法

多态

  • 方法重写实现多态
  • 鸭子类型

特殊方法

  • __str__, __repr__, __eq__
  • 运算符重载

面向对象编程是Python的重要特性,掌握OOP可以帮助你编写更加模块化、可维护的代码。