为什么需要面向对象?
在之前的文章中,我们学习了函数、装饰器、文件操作和异常处理。这些都是过程式编程的核心概念。但当你需要管理复杂的状态和行为时,过程式代码会变得难以维护。
面向对象编程 ( 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()) # 喵喵~
最佳实践建议
- 类名使用大驼峰命名 :
MyClass而不是my_class - 方法名使用小写 + 下划线 :
get_data()而不是getData() - 用
_前缀表示内部属性 :_internal_value - 保持类职责单一:一个类只做一件事
- 优先使用组合而非 继承:避免过深的继承层次
小结
今天我们学习了:
- ✅ 类的定义与实例化
- ✅
self参数的作用 - ✅ 类属性与实例属性的区别
- ✅
@property装饰器 - ✅ 继承的基本用法