Python 面向对象编程基础:类与对象

为什么需要面向对象?

在之前的文章中,我们学习了函数、装饰器、文件操作和异常处理。这些都是过程式编程的核心概念。但当你需要管理复杂的状态和行为时,过程式代码会变得难以维护。

面向对象编程 OOP 提供了一种更好的组织方式:将数据和方法打包成"对象",让代码更模块化、更易扩展。

类的定义与实例化

最简单的类

python 复制代码
class Person:
    """一个简单的类示例"""
    pass

# 创建实例
p1 = Person()
p2 = Person()

print(p1)  # <__main__.Person object at 0x...>
print(p1 == p2)  # False,每个实例都是独立的

带有属性和方法的类

python 复制代码
class Person:
    """表示一个人的类"""
    
    def __init__(self, name, age):
        """初始化方法,创建实例时自动调用"""
        self.name = name  # 实例属性
        self.age = age
    
    def greet(self):
        """实例方法"""
        return f"你好,我是{self.name},今年{self.age}岁"
    
    def birthday(self):
        """过生日,年龄 +1"""
        self.age += 1
        return f"{self.name}过生日了,现在{self.age}岁"

# 使用类
person = Person("张三", 25)
print(person.greet())      # 你好,我是张三,今年 25 岁
print(person.birthday())   # 张三过生日了,现在 26 岁
print(person.age)          # 26

理解 self 参数

self 是 Python 面向对象的核心概念:

ruby 复制代码
class Counter:
    def __init__(self, start=0):
        self.count = start  # self 指向当前实例
    
    def increment(self):
        self.count += 1     # 修改当前实例的属性
        return self.count
    
    def reset(self):
        self.count = 0
        return "已重置"

# 两个独立的计数器
c1 = Counter(10)
c2 = Counter(100)

c1.increment()  # c1.count = 11
c2.increment()  # c2.count = 101

print(c1.count)  # 11
print(c2.count)  # 101

self 确保每个实例有自己的独立状态。

类属性 vs 实例属性

python 复制代码
class Student:
    # 类属性:所有实例共享
    school = "Python 学院"
    student_count = 0
    
    def __init__(self, name, grade):
        # 实例属性:每个实例独立
        self.name = name
        self.grade = grade
        Student.student_count += 1  # 修改类属性
    
    def info(self):
        return f"{self.name} - {self.grade}年级 - {Student.school}"

s1 = Student("小明", 3)
s2 = Student("小红", 5)

print(s1.info())  # 小明 - 3 年级 - Python 学院
print(s2.info())  # 小红 - 5 年级 - Python 学院
print(Student.student_count)  # 2,共享的计数器

# 修改类属性会影响所有实例
Student.school = "Python 大学"
print(s1.info())  # 小明 - 3 年级 - Python 大学

实用案例:银行账户管理系统

python 复制代码
class BankAccount:
    """银行账户类"""
    
    def __init__(self, owner, balance=0):
        self.owner = owner
        self._balance = balance  # 约定:_ 开头表示"受保护"
        self._transaction_history = []
    
    @property
    def balance(self):
        """余额的只读属性"""
        return self._balance
    
    def deposit(self, amount):
        """存款"""
        if amount <= 0:
            raise ValueError("存款金额必须大于 0")
        self._balance += amount
        self._transaction_history.append(f"+{amount}")
        return f"存入{amount},当前余额:{self._balance}"
    
    def withdraw(self, amount):
        """取款"""
        if amount <= 0:
            raise ValueError("取款金额必须大于 0")
        if amount > self._balance:
            raise ValueError("余额不足")
        self._balance -= amount
        self._transaction_history.append(f"-{amount}")
        return f"取出{amount},当前余额:{self._balance}"
    
    def get_statement(self):
        """获取交易记录"""
        return f"{self.owner}的账户记录:{self._transaction_history}"

# 使用示例
account = BankAccount("李四", 1000)
print(account.deposit(500))    # 存入 500,当前余额:1500
print(account.withdraw(200))   # 取出 200,当前余额:1300
print(account.balance)         # 1300(通过@property 访问)
print(account.get_statement()) # 李四的账户记录:['+500', '-200']

# 尝试非法操作
try:
    account.withdraw(2000)  # 余额不足
except ValueError as e:
    print(f"错误:{e}")

继承:代码复用的利器

ruby 复制代码
# 基类
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        return "..."
    
    def info(self):
        return f"我是{self.name}"

# 派生类
class Dog(Animal):
    def speak(self):
        return "汪汪!"
    
    def fetch(self):
        return f"{self.name}去捡球了"

class Cat(Animal):
    def speak(self):
        return "喵喵~"
    
    def climb(self):
        return f"{self.name}爬树去了"

# 使用继承
dog = Dog("旺财")
cat = Cat("咪咪")

print(dog.info())   # 我是旺财(继承自 Animal)
print(dog.speak())  # 汪汪!(重写方法)
print(dog.fetch())  # 旺财去捡球了(Dog 特有方法)

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

最佳实践建议

  1. 类名使用大驼峰命名MyClass 而不是 my_class
  2. 方法名使用小写 + 下划线get_data() 而不是 getData()
  3. _ 前缀表示内部属性_internal_value
  4. 保持类职责单一:一个类只做一件事
  5. 优先使用组合而非 继承:避免过深的继承层次

小结

今天我们学习了:

  • ✅ 类的定义与实例化
  • self 参数的作用
  • ✅ 类属性与实例属性的区别
  • @property 装饰器
  • ✅ 继承的基本用法
相关推荐
Csvn3 小时前
异常处理与错误调试
python
yy我不解释3 小时前
关于comfyui的mmaudio音频生成插件时时间不一致问题(四)(video upload)(解决方法)
开发语言·python·ai作画·音视频·comfyui
2301_776508723 小时前
用Python和Twilio构建短信通知系统
jvm·数据库·python
紫丁香3 小时前
pytest_自动化测试5
python·功能测试·单元测试·集成测试·pytest
姚青&3 小时前
Pytest fixture 参数化(params 参数)
开发语言·python·pytest
2301_793804693 小时前
深入理解Python的if __name__ == ‘__main__‘
jvm·数据库·python
qyzm3 小时前
牛客周赛 Round 136
数据结构·python·算法
紫檀香3 小时前
Alembic入门教程
后端·python
2401_833197733 小时前
用Python生成艺术:分形与算法绘图
jvm·数据库·python