Appearance
Python 面向对象编程
面向对象编程(Object-Oriented Programming,简称 OOP)是一种编程范式,它将数据和操作数据的方法封装在一起,形成对象。本章节将详细介绍 Python 中的面向对象编程概念和实践。
基本概念
类(Class)
类是对象的蓝图或模板,定义了对象的属性和方法。
对象(Object)
对象是类的实例,具有类定义的属性和方法。
属性(Attribute)
属性是对象的特征,如颜色、大小等。
方法(Method)
方法是对象的行为,如移动、计算等。
继承(Inheritance)
继承是指一个类可以继承另一个类的属性和方法。
多态(Polymorphism)
多态是指不同类的对象可以响应相同的方法调用,但行为不同。
封装(Encapsulation)
封装是指将数据和方法封装在类中,对外部隐藏实现细节。
抽象(Abstraction)
抽象是指只暴露必要的接口,隐藏不必要的细节。
类的定义
基本语法
python
class ClassName:
# 类变量
class_variable = value
# 初始化方法
def __init__(self, parameter1, parameter2, ...):
# 实例变量
self.instance_variable1 = parameter1
self.instance_variable2 = parameter2
...
# 实例方法
def method_name(self, parameter1, parameter2, ...):
# 方法体
...
# 类方法
@classmethod
def class_method(cls, parameter1, parameter2, ...):
# 方法体
...
# 静态方法
@staticmethod
def static_method(parameter1, parameter2, ...):
# 方法体
...示例 1:简单类
python
# 简单类
class Person:
"""Person 类"""
# 类变量
species = "人类"
# 初始化方法
def __init__(self, name, age):
"""初始化方法"""
self.name = name # 实例变量
self.age = age # 实例变量
# 实例方法
def greet(self):
"""问候方法"""
print(f"你好,我是 {self.name},今年 {self.age} 岁。")
# 实例方法
def celebrate_birthday(self):
"""庆祝生日方法"""
self.age += 1
print(f"生日快乐!现在 {self.name} 是 {self.age} 岁了。")
# 创建对象
person1 = Person("Alice", 30)
person2 = Person("Bob", 25)
# 访问类变量
print(f"person1 的物种:{person1.species}")
print(f"person2 的物种:{person2.species}")
print(f"Person 类的物种:{Person.species}")
# 访问实例变量
print(f"person1 的名字:{person1.name}")
print(f"person1 的年龄:{person1.age}")
print(f"person2 的名字:{person2.name}")
print(f"person2 的年龄:{person2.age}")
# 调用实例方法
person1.greet()
person2.greet()
# 调用方法修改属性
person1.celebrate_birthday()
print(f"person1 的年龄:{person1.age}")输出:
person1 的物种:人类
person2 的物种:人类
Person 类的物种:人类
person1 的名字:Alice
person1 的年龄:30
person2 的名字:Bob
person2 的年龄:25
你好,我是 Alice,今年 30 岁。
你好,我是 Bob,今年 25 岁。
生日快乐!现在 Alice 是 31 岁了。
person1 的年龄:31示例 2:类方法和静态方法
python
# 类方法和静态方法
class MathUtils:
"""数学工具类"""
# 类变量
PI = 3.14159
# 初始化方法
def __init__(self, radius):
"""初始化方法"""
self.radius = radius
# 实例方法
def calculate_circle_area(self):
"""计算圆的面积"""
return self.PI * self.radius ** 2
# 类方法
@classmethod
def set_pi(cls, value):
"""设置 PI 的值"""
cls.PI = value
print(f"PI 的值已设置为:{cls.PI}")
# 静态方法
@staticmethod
def add(a, b):
"""计算两个数的和"""
return a + b
# 静态方法
@staticmethod
def multiply(a, b):
"""计算两个数的乘积"""
return a * b
# 使用实例方法
math_obj = MathUtils(5)
area = math_obj.calculate_circle_area()
print(f"圆的面积:{area}")
# 使用类方法
MathUtils.set_pi(3.14)
area = math_obj.calculate_circle_area()
print(f"更新 PI 后圆的面积:{area}")
# 使用静态方法
print(f"2 + 3 = {MathUtils.add(2, 3)}")
print(f"2 * 3 = {MathUtils.multiply(2, 3)}")输出:
圆的面积:78.53975
PI 的值已设置为:3.14
更新 PI 后圆的面积:78.5
2 + 3 = 5
2 * 3 = 6继承
基本语法
python
class ParentClass:
# 父类定义
pass
class ChildClass(ParentClass):
# 子类定义
pass示例 1:单继承
python
# 单继承
class Animal:
"""动物类"""
def __init__(self, name):
"""初始化方法"""
self.name = name
def speak(self):
"""说话方法"""
print(f"{self.name} 发出声音。")
class Dog(Animal):
"""狗类"""
def speak(self):
"""重写说话方法"""
print(f"{self.name} 汪汪叫。")
class Cat(Animal):
"""猫类"""
def speak(self):
"""重写说话方法"""
print(f"{self.name} 喵喵叫。")
# 创建对象
animal = Animal("动物")
dog = Dog("小狗")
cat = Cat("小猫")
# 调用方法
animal.speak()
dog.speak()
cat.speak()输出:
动物 发出声音。
小狗 汪汪叫。
小猫 喵喵叫。示例 2:多继承
python
# 多继承
class A:
"""类 A"""
def method_a(self):
"""方法 A"""
print("方法 A")
class B:
"""类 B"""
def method_b(self):
"""方法 B"""
print("方法 B")
class C(A, B):
"""类 C,继承自 A 和 B"""
def method_c(self):
"""方法 C"""
print("方法 C")
# 创建对象
c = C()
# 调用继承的方法
c.method_a()
c.method_b()
# 调用自己的方法
c.method_c()输出:
方法 A
方法 B
方法 C示例 3:super() 函数
python
# super() 函数
class Parent:
"""父类"""
def __init__(self, name):
"""初始化方法"""
self.name = name
print(f"父类初始化:{self.name}")
def method(self):
"""父类方法"""
print(f"父类方法:{self.name}")
class Child(Parent):
"""子类"""
def __init__(self, name, age):
"""初始化方法"""
super().__init__(name) # 调用父类的初始化方法
self.age = age
print(f"子类初始化:{self.name}, {self.age}")
def method(self):
"""子类方法"""
super().method() # 调用父类的方法
print(f"子类方法:{self.name}, {self.age}")
# 创建对象
child = Child("Alice", 30)
# 调用方法
child.method()输出:
父类初始化:Alice
子类初始化:Alice, 30
父类方法:Alice
子类方法:Alice, 30多态
示例
python
# 多态
class Animal:
"""动物类"""
def speak(self):
"""说话方法"""
pass
class Dog(Animal):
"""狗类"""
def speak(self):
"""重写说话方法"""
return "汪汪叫"
class Cat(Animal):
"""猫类"""
def speak(self):
"""重写说话方法"""
return "喵喵叫"
class Cow(Animal):
"""牛类"""
def speak(self):
"""重写说话方法"""
return "哞哞叫"
# 多态函数
def animal_speak(animal):
"""动物说话函数"""
print(f"动物说:{animal.speak()}")
# 创建对象
dog = Dog()
cat = Cat()
cow = Cow()
# 调用多态函数
animal_speak(dog)
animal_speak(cat)
animal_speak(cow)输出:
动物说:汪汪叫
动物说:喵喵叫
动物说:哞哞叫封装
私有属性和方法
在 Python 中,使用双下划线 __ 前缀来定义私有属性和方法。
示例
python
# 封装
class Person:
"""Person 类"""
def __init__(self, name, age, salary):
"""初始化方法"""
self.name = name # 公开属性
self._age = age # 受保护属性
self.__salary = salary # 私有属性
def get_salary(self):
"""获取工资(公开方法)"""
return self.__salary
def set_salary(self, salary):
"""设置工资(公开方法)"""
if salary > 0:
self.__salary = salary
else:
print("工资不能为负数")
def __private_method(self):
"""私有方法"""
print("这是一个私有方法")
def public_method(self):
"""公开方法"""
print("这是一个公开方法")
self.__private_method() # 在类内部可以访问私有方法
# 创建对象
person = Person("Alice", 30, 5000)
# 访问公开属性
print(f"姓名:{person.name}")
# 访问受保护属性(不推荐)
print(f"年龄:{person._age}")
# 尝试访问私有属性(会失败)
try:
print(f"工资:{person.__salary}")
except AttributeError as e:
print(f"错误:{e}")
# 通过公开方法访问私有属性
print(f"工资:{person.get_salary()}")
# 通过公开方法修改私有属性
person.set_salary(6000)
print(f"新工资:{person.get_salary()}")
# 尝试访问私有方法(会失败)
try:
person.__private_method()
except AttributeError as e:
print(f"错误:{e}")
# 通过公开方法调用私有方法
person.public_method()输出:
姓名:Alice
年龄:30
错误:'Person' object has no attribute '__salary'
工资:5000
新工资:6000
错误:'Person' object has no attribute '__private_method'
这是一个公开方法
这是一个私有方法特殊方法
Python 中有许多特殊方法,它们以双下划线 __ 开头和结尾,用于实现对象的特殊行为。
常见特殊方法
| 特殊方法 | 描述 |
|---|---|
__init__ | 初始化方法 |
__str__ | 字符串表示方法 |
__repr__ | 官方字符串表示方法 |
__len__ | 长度方法 |
__getitem__ | 获取元素方法 |
__setitem__ | 设置元素方法 |
__delitem__ | 删除元素方法 |
__iter__ | 迭代器方法 |
__next__ | 下一个元素方法 |
__add__ | 加法方法 |
__sub__ | 减法方法 |
__mul__ | 乘法方法 |
__truediv__ | 除法方法 |
__eq__ | 等于方法 |
__ne__ | 不等于方法 |
__lt__ | 小于方法 |
__le__ | 小于等于方法 |
__gt__ | 大于方法 |
__ge__ | 大于等于方法 |
__contains__ | 包含方法 |
示例:自定义列表类
python
# 自定义列表类
class MyList:
"""自定义列表类"""
def __init__(self, *args):
"""初始化方法"""
self.items = list(args)
def __str__(self):
"""字符串表示方法"""
return f"MyList({self.items})"
def __repr__(self):
"""官方字符串表示方法"""
return f"MyList({self.items})"
def __len__(self):
"""长度方法"""
return len(self.items)
def __getitem__(self, index):
"""获取元素方法"""
return self.items[index]
def __setitem__(self, index, value):
"""设置元素方法"""
self.items[index] = value
def __delitem__(self, index):
"""删除元素方法"""
del self.items[index]
def __iter__(self):
"""迭代器方法"""
return iter(self.items)
def __add__(self, other):
"""加法方法"""
if isinstance(other, MyList):
return MyList(*(self.items + other.items))
elif isinstance(other, list):
return MyList(*(self.items + other))
else:
raise TypeError("不支持的操作数类型")
def __contains__(self, item):
"""包含方法"""
return item in self.items
def append(self, item):
"""追加方法"""
self.items.append(item)
def remove(self, item):
"""移除方法"""
self.items.remove(item)
# 创建对象
my_list = MyList(1, 2, 3, 4, 5)
print(f"my_list: {my_list}")
# 测试长度方法
print(f"长度: {len(my_list)}")
# 测试获取元素方法
print(f"第一个元素: {my_list[0]}")
print(f"最后一个元素: {my_list[-1]}")
# 测试设置元素方法
my_list[0] = 10
print(f"修改后: {my_list}")
# 测试删除元素方法
del my_list[4]
print(f"删除后: {my_list}")
# 测试迭代
print("迭代:")
for item in my_list:
print(item)
# 测试加法
my_list2 = MyList(6, 7, 8)
result = my_list + my_list2
print(f"加法结果: {result}")
# 测试包含
print(f"3 在 my_list 中: {3 in my_list}")
print(f"100 在 my_list 中: {100 in my_list}")
# 测试其他方法
my_list.append(9)
print(f"追加后: {my_list}")
my_list.remove(2)
print(f"移除后: {my_list}")输出:
my_list: MyList([1, 2, 3, 4, 5])
长度: 5
第一个元素: 1
最后一个元素: 5
修改后: MyList([10, 2, 3, 4, 5])
删除后: MyList([10, 2, 3, 4])
迭代:
10
2
3
4
加法结果: MyList([10, 2, 3, 4, 6, 7, 8])
3 在 my_list 中: True
100 在 my_list 中: False
追加后: MyList([10, 2, 3, 4, 9])
移除后: MyList([10, 3, 4, 9])抽象类
抽象类是不能实例化的类,用于定义接口。在 Python 中,使用 abc 模块来创建抽象类。
示例
python
# 抽象类
from abc import ABC, abstractmethod
class Shape(ABC):
"""形状抽象类"""
@abstractmethod
def calculate_area(self):
"""计算面积(抽象方法)"""
pass
@abstractmethod
def calculate_perimeter(self):
"""计算周长(抽象方法)"""
pass
class Circle(Shape):
"""圆形类"""
def __init__(self, radius):
"""初始化方法"""
self.radius = radius
def calculate_area(self):
"""计算面积"""
import math
return math.pi * self.radius ** 2
def calculate_perimeter(self):
"""计算周长"""
import math
return 2 * math.pi * self.radius
class Rectangle(Shape):
"""矩形类"""
def __init__(self, length, width):
"""初始化方法"""
self.length = length
self.width = width
def calculate_area(self):
"""计算面积"""
return self.length * self.width
def calculate_perimeter(self):
"""计算周长"""
return 2 * (self.length + self.width)
# 尝试实例化抽象类(会失败)
try:
shape = Shape()
except TypeError as e:
print(f"错误:{e}")
# 创建子类对象
circle = Circle(5)
print(f"圆形面积:{circle.calculate_area():.2f}")
print(f"圆形周长:{circle.calculate_perimeter():.2f}")
rectangle = Rectangle(4, 6)
print(f"矩形面积:{rectangle.calculate_area()}")
print(f"矩形周长:{rectangle.calculate_perimeter()}")输出:
错误:Can't instantiate abstract class Shape with abstract methods calculate_area, calculate_perimeter
圆形面积:78.54
圆形周长:31.42
矩形面积:24
矩形周长:20实际应用示例
示例 1:学生管理系统
python
# 学生管理系统
class Student:
"""学生类"""
def __init__(self, id, name, age, grade):
"""初始化方法"""
self.id = id
self.name = name
self.age = age
self.grade = grade
def __str__(self):
"""字符串表示方法"""
return f"ID: {self.id}, 姓名: {self.name}, 年龄: {self.age}, 成绩: {self.grade}"
class StudentManager:
"""学生管理类"""
def __init__(self):
"""初始化方法"""
self.students = []
def add_student(self, student):
"""添加学生"""
self.students.append(student)
print(f"添加学生成功:{student.name}")
def remove_student(self, student_id):
"""删除学生"""
for student in self.students:
if student.id == student_id:
self.students.remove(student)
print(f"删除学生成功:{student.name}")
return True
print(f"学生 ID {student_id} 不存在")
return False
def find_student(self, student_id):
"""查找学生"""
for student in self.students:
if student.id == student_id:
return student
return None
def list_students(self):
"""列出所有学生"""
if not self.students:
print("没有学生记录")
return
print("学生列表:")
for student in self.students:
print(student)
def update_student(self, student_id, **kwargs):
"""更新学生信息"""
student = self.find_student(student_id)
if student:
for key, value in kwargs.items():
if hasattr(student, key):
setattr(student, key, value)
print(f"更新学生成功:{student.name}")
return True
print(f"学生 ID {student_id} 不存在")
return False
# 测试
manager = StudentManager()
# 添加学生
student1 = Student(1, "Alice", 18, 95)
student2 = Student(2, "Bob", 17, 88)
student3 = Student(3, "Charlie", 19, 92)
manager.add_student(student1)
manager.add_student(student2)
manager.add_student(student3)
# 列出学生
print("\n列出所有学生:")
manager.list_students()
# 查找学生
print("\n查找学生:")
found = manager.find_student(2)
if found:
print(f"找到学生:{found}")
else:
print("学生不存在")
# 更新学生
print("\n更新学生:")
manager.update_student(2, age=18, grade=90)
# 列出学生
print("\n列出所有学生:")
manager.list_students()
# 删除学生
print("\n删除学生:")
manager.remove_student(3)
# 列出学生
print("\n列出所有学生:")
manager.list_students()输出:
添加学生成功:Alice
添加学生成功:Bob
添加学生成功:Charlie
列出所有学生:
学生列表:
ID: 1, 姓名: Alice, 年龄: 18, 成绩: 95
ID: 2, 姓名: Bob, 年龄: 17, 成绩: 88
ID: 3, 姓名: Charlie, 年龄: 19, 成绩: 92
查找学生:
找到学生:ID: 2, 姓名: Bob, 年龄: 17, 成绩: 88
更新学生:
更新学生成功:Bob
列出所有学生:
学生列表:
ID: 1, 姓名: Alice, 年龄: 18, 成绩: 95
ID: 2, 姓名: Bob, 年龄: 18, 成绩: 90
ID: 3, 姓名: Charlie, 年龄: 19, 成绩: 92
删除学生:
删除学生成功:Charlie
列出所有学生:
学生列表:
ID: 1, 姓名: Alice, 年龄: 18, 成绩: 95
ID: 2, 姓名: Bob, 年龄: 18, 成绩: 90示例 2:银行账户系统
python
# 银行账户系统
class Account:
"""账户基类"""
def __init__(self, account_number, balance=0):
"""初始化方法"""
self.account_number = account_number
self.balance = balance
def deposit(self, amount):
"""存款"""
if amount > 0:
self.balance += amount
print(f"存款成功:{amount} 元")
print(f"当前余额:{self.balance} 元")
else:
print("存款金额必须大于 0")
def withdraw(self, amount):
"""取款"""
if amount > 0:
if amount <= self.balance:
self.balance -= amount
print(f"取款成功:{amount} 元")
print(f"当前余额:{self.balance} 元")
else:
print("余额不足")
else:
print("取款金额必须大于 0")
def get_balance(self):
"""获取余额"""
return self.balance
def __str__(self):
"""字符串表示方法"""
return f"账户号:{self.account_number}, 余额:{self.balance} 元"
class SavingsAccount(Account):
"""储蓄账户"""
def __init__(self, account_number, balance=0, interest_rate=0.01):
"""初始化方法"""
super().__init__(account_number, balance)
self.interest_rate = interest_rate
def add_interest(self):
"""添加利息"""
interest = self.balance * self.interest_rate
self.balance += interest
print(f"添加利息:{interest:.2f} 元")
print(f"当前余额:{self.balance:.2f} 元")
def __str__(self):
"""字符串表示方法"""
return f"储蓄账户 - 账户号:{self.account_number}, 余额:{self.balance} 元, 利率:{self.interest_rate:.2%}"
class CheckingAccount(Account):
"""支票账户"""
def __init__(self, account_number, balance=0, overdraft_limit=1000):
"""初始化方法"""
super().__init__(account_number, balance)
self.overdraft_limit = overdraft_limit
def withdraw(self, amount):
"""取款(支持透支)"""
if amount > 0:
if amount <= self.balance + self.overdraft_limit:
self.balance -= amount
print(f"取款成功:{amount} 元")
print(f"当前余额:{self.balance} 元")
else:
print(f"超过透支限额,最大可取:{self.balance + self.overdraft_limit} 元")
else:
print("取款金额必须大于 0")
def __str__(self):
"""字符串表示方法"""
return f"支票账户 - 账户号:{self.account_number}, 余额:{self.balance} 元, 透支限额:{self.overdraft_limit} 元"
# 测试
print("=== 储蓄账户 ===")
savings = SavingsAccount("SA123", 10000)
print(savings)
savings.deposit(5000)
savings.withdraw(2000)
savings.add_interest()
print("\n=== 支票账户 ===")
checking = CheckingAccount("CA456", 5000, 2000)
print(checking)
checking.deposit(1000)
checking.withdraw(8000) # 测试透支
checking.withdraw(1000) # 再次取款输出:
=== 储蓄账户 ===
储蓄账户 - 账户号:SA123, 余额:10000 元, 利率:1.00%
存款成功:5000 元
当前余额:15000 元
取款成功:2000 元
当前余额:13000 元
添加利息:130.00 元
当前余额:13130.00 元
=== 支票账户 ===
支票账户 - 账户号:CA456, 余额:5000 元, 透支限额:2000 元
存款成功:1000 元
当前余额:6000 元
取款成功:8000 元
当前余额:-2000 元
取款成功:1000 元
当前余额:-3000 元总结
面向对象编程是 Python 中的重要编程范式,本章节介绍了:
- 基本概念:类、对象、属性、方法、继承、多态、封装、抽象
- 类的定义:实例变量、类变量、实例方法、类方法、静态方法
- 继承:单继承、多继承、super() 函数
- 多态:不同类的对象响应相同的方法调用
- 封装:私有属性和方法
- 特殊方法:
__init__、__str__、__len__等 - 抽象类:使用 abc 模块创建抽象类
- 实际应用示例:学生管理系统、银行账户系统
通过面向对象编程,可以使代码更加模块化、可维护和可扩展。掌握面向对象编程的概念和技巧,对于编写复杂的 Python 程序非常重要。