1. 概述
面向对象编程(Object-Oriented Programming, OOP)是一种编程范式,它将数据和操作数据的方法封装在一起,形成对象,并通过对象之间的交互来构建程序。Python是一种支持面向对象编程的高级编程语言,它提供了丰富的面向对象特性。
1.1 面向对象的核心概念
- 对象(Object):客观世界中的实体,具有属性(数据)和方法(操作)
- 类(Class):对象的模板或蓝图,定义了对象的属性和方法
- 实例化(Instantiation):根据类创建对象的过程
- 继承(Inheritance):一个类继承另一个类的属性和方法
- 多态(Polymorphism):不同类型的对象可以以相同的方式响应相同的消息
- 封装(Encapsulation):将数据和方法封装在对象内部,对外部隐藏实现细节
- 抽象(Abstraction):只展示对象的必要特性,隐藏复杂的实现细节
1.2 Python面向对象的特点
2. 类和对象
2.1 定义类
在Python中,使用class关键字定义类:
# 定义一个简单的类
classPerson:
# 类属性(所有实例共享)
species ="人类"
# 构造方法
def__init__(self, name, age):
# 实例属性(每个实例独有)
self.name = name
self.age = age
# 实例方法
defgreet(self):
print(f"你好,我叫{self.name},今年{self.age}岁。")
# 实例方法
defhave_birthday(self):
self.age +=1
print(f"生日快乐!{self.name}现在{self.age}岁了。")
2.2 创建对象(实例化)
# 创建Person类的实例
person1 = Person("张三",30)
person2 = Person("李四",25)
# 访问实例属性
print(person1.name)# 输出: 张三
print(person2.age)# 输出: 25
# 调用实例方法
person1.greet()# 输出: 你好,我叫张三,今年30岁。
person2.have_birthday()# 输出: 生日快乐!李四现在26岁了。
# 访问类属性
print(Person.species)# 输出: 人类
print(person1.species)# 输出: 人类
print(person2.species)# 输出: 人类
# 修改类属性
Person.species ="智人"
print(person1.species)# 输出: 智人
2.3 __init__构造方法
__init__方法是类的构造方法,在创建对象时自动调用:
classCar:
def__init__(self, brand, model, year):
self.brand = brand
self.model = model
self.year = year
self.mileage =0# 默认属性
defdrive(self, distance):
self.mileage += distance
print(f"行驶了{distance}公里,总里程:{self.mileage}公里。")
# 创建Car实例
my_car = Car("Toyota","Camry",2020)
print(f"我的车:{my_car.brand}{my_car.model}{my_car.year}")
my_car.drive(100)
2.4 __del__析构方法
__del__方法是类的析构方法,在对象被销毁时自动调用:
classFileHandler:
def__init__(self, filename):
self.filename = filename
self.file=open(filename,"r")
print(f"打开文件:{filename}")
defread_content(self):
return self.file.read()
def__del__(self):
self.file.close()
print(f"关闭文件:{self.filename}")
# 创建实例
handler = FileHandler("example.txt")
content = handler.read_content()
print(content)
# 销毁实例
del handler
3. 属性
3.1 实例属性
实例属性是每个对象独有的属性,在__init__方法或其他实例方法中定义:
classDog:
def__init__(self, name, breed):
self.name = name # 实例属性
self.breed = breed # 实例属性
self.age =0# 实例属性(默认值)
defgrow_up(self):
self.age +=1# 在实例方法中修改实例属性
# 创建两个Dog实例
dog1 = Dog("Buddy","Golden Retriever")
dog2 = Dog("Max","German Shepherd")
# 每个实例都有自己的属性
dog1.grow_up()
print(f"{dog1.name} ({dog1.breed}):{dog1.age}岁")# 输出: Buddy (Golden Retriever):1岁
print(f"{dog2.name} ({dog2.breed}):{dog2.age}岁")# 输出: Max (German Shepherd):0岁
3.2 类属性
类属性是类的所有实例共享的属性,在类定义中直接定义:
classStudent:
# 类属性
school_name ="北京大学"
student_count =0
def__init__(self, name, major):
self.name = name # 实例属性
self.major = major # 实例属性
Student.student_count +=1# 访问类属性
# 创建Student实例
student1 = Student("张三","计算机科学")
student2 = Student("李四","物理学")
# 所有实例共享类属性
print(student1.school_name)# 输出: 北京大学
print(student2.school_name)# 输出: 北京大学
print(Student.school_name)# 输出: 北京大学
# 修改类属性
Student.school_name ="清华大学"
print(student1.school_name)# 输出: 清华大学
print(student2.school_name)# 输出: 清华大学
# 学生总数
print(f"学生总数:{Student.student_count}")# 输出: 学生总数:2
3.3 属性访问控制
Python通过命名约定来实现属性的访问控制:
- 公开属性
- 受保护属性:以单下划线
_开头,不应该被外部直接访问(但技术上可以) - 私有属性:以双下划线
__开头,会被Python重命名,外部无法直接访问
classBankAccount:
def__init__(self, account_number, balance):
self.account_number = account_number # 公开属性
self._balance = balance # 受保护属性
self.__pin =1234# 私有属性
defdeposit(self, amount):
if amount >0:
self._balance += amount
print(f"存款{amount}元,余额:{self._balance}元")
defwithdraw(self, amount, pin):
if pin == self.__pin and amount >0and amount <= self._balance:
self._balance -= amount
print(f"取款{amount}元,余额:{self._balance}元")
else:
print("取款失败")
defget_balance(self):
return self._balance
# 创建BankAccount实例
account = BankAccount("1234567890",1000)
# 访问公开属性
print(f"账号:{account.account_number}")
# 访问受保护属性(不推荐)
print(f"余额(直接访问):{account._balance}")
# 通过方法访问受保护属性(推荐)
print(f"余额(方法访问):{account.get_balance()}")
# 尝试访问私有属性(会引发AttributeError)
try:
print(f"PIN码:{account.__pin}")
except AttributeError as e:
print(f"错误:{e}")
# 实际存储的私有属性名称(Python重命名)
print(f"实际私有属性名:{account._BankAccount__pin}")# 输出: 实际私有属性名:1234
# 使用方法操作账户
account.deposit(500)
account.withdraw(300,1234)
account.withdraw(300,0000)# 密码错误
3.4 属性装饰器
Python提供了@property、@property.setter和@property.deleter装饰器来控制属性的访问:
classPerson:
def__init__(self, name, age):
self._name = name
self._age = age
@property
defname(self):
"""获取姓名"""
return self._name
@property
defage(self):
"""获取年龄"""
return self._age
@age.setter
defage(self, value):
"""设置年龄,确保年龄为正整数"""
ifisinstance(value,int)and value >0:
self._age = value
else:
raise ValueError("年龄必须是正整数")
@age.deleter
defage(self):
"""删除年龄属性"""
del self._age
# 创建Person实例
person = Person("张三",30)
# 访问属性(通过property)
print(f"姓名:{person.name}")
print(f"年龄:{person.age}")
# 设置属性(通过property.setter)
try:
person.age =31
print(f"新年龄:{person.age}")
person.age =-5# 无效年龄
except ValueError as e:
print(f"错误:{e}")
# 删除属性(通过property.deleter)
del person.age
try:
print(person.age)
except AttributeError:
print("年龄属性已删除")
4. 方法
4.1 实例方法
实例方法是最常用的方法类型,第一个参数必须是self,代表当前实例:
classCircle:
def__init__(self, radius):
self.radius = radius
# 实例方法
defarea(self):
"""计算圆的面积"""
return3.14159* self.radius **2
# 实例方法
defcircumference(self):
"""计算圆的周长"""
return2*3.14159* self.radius
# 创建Circle实例
circle = Circle(5)
# 调用实例方法
print(f"半径:{circle.radius}")
print(f"面积:{circle.area()}")
print(f"周长:{circle.circumference()}")
4.2 类方法
类方法使用@classmethod装饰器定义,第一个参数必须是cls,代表当前类:
classDate:
def__init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def__str__(self):
returnf"{self.year}-{self.month:02d}-{self.day:02d}"
# 类方法
@classmethod
deffrom_string(cls, date_string):
"""从字符串创建Date对象"""
year, month, day =map(int, date_string.split("-"))
return cls(year, month, day)# 调用构造方法
# 类方法
@classmethod
deftoday(cls):
"""获取当前日期"""
from datetime import datetime
now = datetime.now()
return cls(now.year, now.month, now.day)
# 使用构造方法创建Date实例
date1 = Date(2023,5,20)
print(date1)
# 使用类方法创建Date实例
date2 = Date.from_string("2023-05-21")
print(date2)
# 使用类方法获取当前日期
date3 = Date.today()
print(date3)
4.3 静态方法
静态方法使用@staticmethod装饰器定义,没有self或cls参数,与类和实例无关:
classMathUtils:
# 静态方法
@staticmethod
defadd(a, b):
"""加法"""
return a + b
# 静态方法
@staticmethod
defmultiply(a, b):
"""乘法"""
return a * b
# 静态方法
@staticmethod
defis_even(number):
"""判断是否为偶数"""
return number %2==0
# 直接通过类调用静态方法
print(f"1 + 2 = {MathUtils.add(1,2)}")
print(f"3 * 4 = {MathUtils.multiply(3,4)}")
print(f"5是偶数吗?{MathUtils.is_even(5)}")
print(f"6是偶数吗?{MathUtils.is_even(6)}")
# 也可以通过实例调用静态方法(不推荐)
math_utils = MathUtils()
print(f"7 + 8 = {math_utils.add(7,8)}")
5. 继承
继承是面向对象编程的重要特性,它允许一个类继承另一个类的属性和方法:
5.1 基本继承
# 父类(基类)
classAnimal:
def__init__(self, name):
self.name = name
defeat(self):
print(f"{self.name}正在吃东西")
defsleep(self):
print(f"{self.name}正在睡觉")
# 子类(派生类)继承Animal
classDog(Animal):
def__init__(self, name, breed):
super().__init__(name)# 调用父类的构造方法
self.breed = breed
defbark(self):
print(f"{self.name}({self.breed})正在汪汪叫")
# 子类(派生类)继承Animal
classCat(Animal):
def__init__(self, name, color):
super().__init__(name)# 调用父类的构造方法
self.color = color
defmeow(self):
print(f"{self.name}({self.color})正在喵喵叫")
# 创建Dog实例
dog = Dog("Buddy","Golden Retriever")
dog.eat()# 继承自父类
dog.sleep()# 继承自父类
dog.bark()# 子类自己的方法
# 创建Cat实例
cat = Cat("Kitty","白色")
cat.eat()# 继承自父类
cat.sleep()# 继承自父类
cat.meow()# 子类自己的方法
5.2 方法重写
子类可以重写父类的方法,实现自己的行为:
classAnimal:
def__init__(self, name):
self.name = name
defmake_sound(self):
print(f"{self.name}发出声音")
classDog(Animal):
defmake_sound(self):
print(f"{self.name}汪汪叫")
classCat(Animal):
defmake_sound(self):
print(f"{self.name}喵喵叫")
classCow(Animal):
defmake_sound(self):
print(f"{self.name}哞哞叫")
# 创建实例
animals =[Dog("Buddy"), Cat("Kitty"), Cow("Bessie")]
# 多态的体现:不同对象以相同方式响应相同消息
for animal in animals:
animal.make_sound()
5.3 多继承
Python支持多继承,一个类可以继承多个父类:
classFlyable:
deffly(self):
print("可以飞行")
classSwimmable:
defswim(self):
print("可以游泳")
# 多继承:Duck同时继承Flyable和Swimmable
classDuck(Flyable, Swimmable):
defquack(self):
print("嘎嘎叫")
# 创建Duck实例
duck = Duck()
duck.fly()# 继承自Flyable
duck.swim()# 继承自Swimmable
duck.quack()# 自己的方法
5.4 继承顺序(MRO)
Python使用C3线性化算法确定多继承的方法解析顺序(Method Resolution Order, MRO):
classA:
defsay(self):
print("A")
classB(A):
defsay(self):
print("B")
classC(A):
defsay(self):
print("C")
classD(B, C):
pass
# 创建D实例
d = D()
d.say()# 输出: B
# 查看MRO
print(D.__mro__)# 输出: (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# 使用super()遵循MRO
classD(B, C):
defsay(self):
super().say()# 调用MRO中的下一个类的方法
# 创建新的D实例
d = D()
d.say()# 输出: B
6. 多态
多态是指不同类型的对象可以以相同的方式响应相同的消息:
classShape:
defarea(self):
raise NotImplementedError("子类必须实现area方法")
classRectangle(Shape):
def__init__(self, width, height):
self.width = width
self.height = height
defarea(self):
return self.width * self.height
classCircle(Shape):
def__init__(self, radius):
self.radius = radius
defarea(self):
return3.14159* self.radius **2
classTriangle(Shape):
def__init__(self, base, height):
self.base = base
self.height = height
defarea(self):
return0.5* self.base * self.height
# 计算不同形状的面积
defcalculate_total_area(shapes):
total =0
for shape in shapes:
total += shape.area()# 多态:不同对象调用相同的area方法
return total
# 创建不同形状的实例
shapes =[
Rectangle(5,10),
Circle(7),
Triangle(8,6)
]
# 计算总面积
total_area = calculate_total_area(shapes)
print(f"总面积:{total_area}")
7. 封装
封装是指将数据和方法封装在对象内部,对外部隐藏实现细节:
classStudent:
def__init__(self, name, student_id):
self._name = name # 受保护属性
self._student_id = student_id # 受保护属性
self._grades ={}# 受保护属性
defadd_grade(self, course, grade):
"""添加成绩"""
if0<= grade <=100:
self._grades[course]= grade
else:
raise ValueError("成绩必须在0-100之间")
defget_grade(self, course):
"""获取指定课程的成绩"""
return self._grades.get(course,"未选修该课程")
defget_average_grade(self):
"""获取平均成绩"""
ifnot self._grades:
return0
returnsum(self._grades.values())/len(self._grades)
@property
defname(self):
"""获取姓名"""
return self._name
@property
defstudent_id(self):
"""获取学号"""
return self._student_id
# 创建Student实例
student = Student("张三","2023001")
# 设置成绩
student.add_grade("数学",90)
student.add_grade("英语",85)
student.add_grade("计算机",95)
# 获取成绩
print(f"姓名:{student.name}")
print(f"学号:{student.student_id}")
print(f"数学成绩:{student.get_grade('数学')}")
print(f"平均成绩:{student.get_average_grade()}")
# 尝试直接修改属性(不推荐)
student._grades["数学"]=110# 绕过了验证
print(f"数学成绩(直接修改):{student.get_grade('数学')}")
8. 特殊方法
Python提供了许多特殊方法(也称为魔术方法),用于实现对象的特殊行为:
8.1 字符串表示方法
__str__:返回对象的字符串表示,用于print()和str()__repr__
classBook:
def__init__(self, title, author, year):
self.title = title
self.author = author
self.year = year
def__str__(self):
return f"《{self.title}》-{self.author}({self.year})
def__repr__(self):
return f"Book(title='{self.title}', author='{self.author}', year={self.year})
# 创建Book实例
book = Book("Python编程","张荣殿",2023)
# 使用print()调用__str__
print(book)# 输出: 《Python编程》- 张荣殿 (2023)
# 使用str()调用__str__
print(str(book))# 输出: 《Python编程》- 张荣殿 (2023)
# 使用repr()调用__repr__
print(repr(book))# 输出: Book(title='Python编程', author='张荣殿', year=2023)
# 在交互式环境中直接输入对象会调用__repr__
# >>> book
# Book(title='Python编程', author='张荣殿', year=2023)
8.2 比较方法
__eq____ne____lt____le____gt____ge__
classPoint:
def__init__(self, x, y):
self.x = x
self.y = y
def__eq__(self, other):
"""等于"""
ifnotisinstance(other, Point):
return NotImplemented
return self.x == other.x and self.y == other.y
def__lt__(self, other):
"""小于"""
ifnotisinstance(other, Point):
return NotImplemented
return(self.x, self.y)<(other.x, other.y)
def__str__(self):
returnf"({self.x}, {self.y})"
# 创建Point实例
p1 = Point(1,2)
p2 = Point(1,2)
p3 = Point(3,4)
# 比较相等
print(f"p1 == p2: {p1 == p2}")# 输出: True
print(f"p1 == p3: {p1 == p3}")# 输出: False
# 比较大小
print(f"p1 < p3: {p1 < p3}")# 输出: True
print(f"p3 < p1: {p3 < p1}")# 输出: False
# 排序
points =[p3, p1, Point(0,5), Point(2,1)]
points.sort()
print(f"排序后的点:{[str(p)for p in points]}")
8.3 算术运算方法
__add____sub____mul____truediv____floordiv____mod__
classVector:
def__init__(self, x, y):
self.x = x
self.y = y
def__add__(self, other):
"""向量加法"""
ifnotisinstance(other, Vector):
return NotImplemented
return Vector(self.x + other.x, self.y + other.y)
def__sub__(self, other):
"""向量减法"""
ifnotisinstance(other, Vector):
return NotImplemented
return Vector(self.x - other.x, self.y - other.y)
def__mul__(self, scalar):
"""向量乘法(与标量)"""
ifnotisinstance(scalar,(int,float)):
return NotImplemented
return Vector(self.x * scalar, self.y * scalar)
def__str__(self):
returnf"Vector({self.x}, {self.y})"
# 创建Vector实例
v1 = Vector(1,2)
v2 = Vector(3,4)
# 向量加法
v3 = v1 + v2
print(f"v1 + v2 = {v3}")
# 向量减法
v4 = v2 - v1
print(f"v2 - v1 = {v4}")
# 向量乘法(与标量)
v5 = v1 *3
print(f"v1 * 3 = {v5}")
8.4 容器类型方法
__len____getitem____setitem____delitem____contains__
classCustomList:
def__init__(self,*items):
self._items =list(items)
def__len__(self):
"""获取长度"""
returnlen(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__contains__(self, item):
"""检查包含"""
return item in self._items
def__str__(self):
returnstr(self._items)
# 创建CustomList实例
my_list = CustomList(1,2,3,4,5)
# 获取长度
print(f"长度:{len(my_list)}")
# 获取元素
print(f"第一个元素:{my_list[0]}")
print(f"最后一个元素:{my_list[-1]}")
# 设置元素
my_list[2]=10
print(f"修改后的列表:{my_list}")
# 删除元素
del my_list[1]
print(f"删除后的列表:{my_list}")
# 检查包含
print(f"10在列表中吗?{10in my_list}")
print(f"2在列表中吗?{2in my_list}")
9. 抽象类和接口
Python使用abc模块实现抽象类和接口:
9.1 抽象类
from abc import ABC, abstractmethod
classShape(ABC):
"""抽象类Shape"""
@abstractmethod
defarea(self):
"""计算面积(抽象方法,必须在子类中实现)"""
pass
@abstractmethod
defperimeter(self):
"""计算周长(抽象方法,必须在子类中实现)"""
pass
defdescribe(self):
"""描述形状(具体方法,子类可以继承)"""
returnf"我是一个形状,面积:{self.area()}, 周长:{self.perimeter()}"
classRectangle(Shape):
"""Rectangle类实现Shape抽象类"""
def__init__(self, width, height):
self.width = width
self.height = height
defarea(self):
"""实现抽象方法area"""
return self.width * self.height
defperimeter(self):
"""实现抽象方法perimeter"""
return2*(self.width + self.height)
classCircle(Shape):
"""Circle类实现Shape抽象类"""
def__init__(self, radius):
self.radius = radius
defarea(self):
"""实现抽象方法area"""
return3.14159* self.radius **2
defperimeter(self):
"""实现抽象方法perimeter"""
return2*3.14159* self.radius
# 创建Rectangle和Circle实例
rectangle = Rectangle(5,10)
circle = Circle(7)
# 调用方法
print(rectangle.describe())
print(circle.describe())
# 尝试实例化抽象类(会引发TypeError)
try:
shape = Shape()
except TypeError as e:
print(f"错误:{e}")
9.2 接口
Python中没有正式的接口概念,但可以使用抽象类实现类似接口的功能:
from abc import ABC, abstractmethod
classDrawable(ABC):
"""Drawable接口"""
@abstractmethod
defdraw(self):
"""绘制方法"""
pass
classResizable(ABC):
"""Resizable接口"""
@abstractmethod
defresize(self, factor):
"""调整大小方法"""
pass
# 实现两个接口
classSquare(Drawable, Resizable):
def__init__(self, side):
self.side = side
defdraw(self):
print(f"绘制一个边长为{self.side}的正方形")
defresize(self, factor):
self.side *= factor
defarea(self):
return self.side **2
# 创建Square实例
square = Square(5)
square.draw()
square.resize(2)
square.draw()
print(f"面积:{square.area()}")
10. 组合和聚合
10.1 组合
组合是一种强关联关系,表示"部分属于整体",整体销毁时,部分也会被销毁:
classEngine:
"""发动机类"""
def__init__(self, power):
self.power = power
defstart(self):
print(f"启动{self.power}马力的发动机")
classWheel:
"""车轮类"""
def__init__(self, size):
self.size = size
classCar:
"""汽车类(组合了Engine和Wheel)"""
def__init__(self, brand, model, engine_power, wheel_size):
self.brand = brand
self.model = model
self.engine = Engine(engine_power)# 组合:Car包含Engine
self.wheels =[Wheel(wheel_size)for _ inrange(4)]# 组合:Car包含4个Wheel
defstart(self):
print(f"启动{self.brand}{self.model}")
self.engine.start()
# 创建Car实例
car = Car("Toyota","Camry",180,17)
car.start()
# 当car被销毁时,其包含的engine和wheels也会被销毁
10.2 聚合
聚合是一种弱关联关系,表示"整体包含部分",整体销毁时,部分不会被销毁:
classAuthor:
"""作者类"""
def__init__(self, name):
self.name = name
self.books =[]# 聚合:Author包含Book,但Book可以独立存在
defadd_book(self, book):
self.books.append(book)
classBook:
"""书籍类"""
def__init__(self, title):
self.title = title
# 创建Author和Book实例
author = Author("张三")
book1 = Book("Python编程")
book2 = Book("Java编程")
# 聚合:将Book添加到Author
author.add_book(book1)
author.add_book(book2)
# 输出作者的书籍
print(f"{author.name}的著作:")
for book in author.books:
print(f"- {book.title}")
# 即使author被销毁,book1和book2仍然存在
11. 面向对象设计原则
11.1 单一职责原则(SRP)
一个类应该只有一个引起它变化的原因:
# 违反SRP的例子
classUser:
def__init__(self, name, email):
self.name = name
self.email = email
defsave(self):
"""保存用户到数据库"""
print(f"保存用户{self.name}到数据库")
defsend_email(self, message):
"""发送邮件"""
print(f"给{self.email}发送邮件:{message}")
# 遵循SRP的例子
classUser:
def__init__(self, name, email):
self.name = name
self.email = email
classUserRepository:
defsave(self, user):
"""保存用户到数据库"""
print(f"保存用户{user.name}到数据库")
classEmailService:
defsend_email(self, user, message):
"""发送邮件"""
print(f"给{user.email}发送邮件:{message}")
11.2 开放封闭原则(OCP)
软件实体(类、模块、函数等)应该对扩展开放,对修改封闭:
# 违反OCP的例子
classShape:
def__init__(self, shape_type,*args):
self.shape_type = shape_type
if shape_type =="rectangle":
self.width, self.height = args
elif shape_type =="circle":
self.radius = args[0]
classAreaCalculator:
defcalculate_area(self, shape):
if shape.shape_type =="rectangle":
return shape.width * shape.height
elif shape.shape_type =="circle":
return3.14159* shape.radius **2
# 添加新形状需要修改calculate_area方法
# 遵循OCP的例子
from abc import ABC, abstractmethod
classShape(ABC):
@abstractmethod
defarea(self):
pass
classRectangle(Shape):
def__init__(self, width, height):
self.width = width
self.height = height
defarea(self):
return self.width * self.height
classCircle(Shape):
def__init__(self, radius):
self.radius = radius
defarea(self):
return3.14159* self.radius **2
# 添加新形状不需要修改AreaCalculator
classTriangle(Shape):
def__init__(self, base, height):
self.base = base
self.height = height
defarea(self):
return0.5* self.base * self.height
classAreaCalculator:
defcalculate_area(self, shape):
return shape.area()# 对扩展开放,对修改封闭
11.3 里氏替换原则(LSP)
子类应该能够替换父类而不改变程序的正确性:
# 违反LSP的例子
classBird:
deffly(self):
print("可以飞行")
classOstrich(Bird):
deffly(self):
raise NotImplementedError("鸵鸟不能飞行")
# 遵循LSP的例子
classBird:
pass
classFlyingBird(Bird):
deffly(self):
print("可以飞行")
classNonFlyingBird(Bird):
pass
classOstrich(NonFlyingBird):
pass
11.4 接口隔离原则(ISP)
客户端不应该依赖它不需要的接口:
# 违反ISP的例子
from abc import ABC, abstractmethod
classWorker(ABC):
@abstractmethod
defwork(self):
pass
@abstractmethod
defeat(self):
pass
classHuman(Worker):
defwork(self):
print("人类工作")
defeat(self):
print("人类吃饭")
classRobot(Worker):
defwork(self):
print("机器人工作")
defeat(self):
# 机器人不需要吃饭,但必须实现该方法
raise NotImplementedError("机器人不需要吃饭")
# 遵循ISP的例子
from abc import ABC, abstractmethod
classWorkable(ABC):
@abstractmethod
defwork(self):
pass
classEatable(ABC):
@abstractmethod
defeat(self):
pass
classHuman(Workable, Eatable):
defwork(self):
print("人类工作")
defeat(self):
print("人类吃饭")
classRobot(Workable):
defwork(self):
print("机器人工作")
# 机器人只实现它需要的接口
11.5 依赖倒置原则(DIP)
高层模块不应该依赖低层模块,两者都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象:
# 违反DIP的例子
classMySQLDatabase:
defsave(self, data):
print(f"保存数据到MySQL: {data}")
classUserService:
def__init__(self):
self.db = MySQLDatabase()# 依赖具体实现
defsave_user(self, user):
self.db.save(user)
# 遵循DIP的例子
from abc import ABC, abstractmethod
classDatabase(ABC):
@abstractmethod
defsave(self, data):
pass
classMySQLDatabase(Database):
defsave(self, data):
print(f"保存数据到MySQL: {data}")
classMongoDB(Database):
defsave(self, data):
print(f"保存数据到MongoDB: {data}")
classUserService:
def__init__(self, db: Database):# 依赖抽象接口
self.db = db
defsave_user(self, user):
self.db.save(user)
# 使用依赖注入
mysql_db = MySQLDatabase()
user_service = UserService(mysql_db)
user_service.save_user({"name":"张三"})
mongo_db = MongoDB()
user_service = UserService(mongo_db)
user_service.save_user({"name":"李四"})
12. 最佳实践
12.1 类命名规范
- 方法和属性名使用小驼峰命名法或下划线命名法(推荐)
classBankAccount:
MIN_BALANCE =0# 常量
def__init__(self, account_number):
self._account_number = account_number # 受保护属性
self.__balance =0# 私有属性
defdeposit(self, amount):
"""存款"""
self.__balance += amount
def_validate_amount(self, amount):
"""验证金额(内部方法)"""
return amount >0
12.2 类的设计
12.3 属性和方法的设计
12.4 异常处理
12.5 测试
13. 总结
面向对象编程是Python编程的重要范式,它将数据和方法封装在一起,形成对象,并通过对象之间的交互来构建程序。本文详细介绍了Python面向对象编程的核心概念:
- 类和对象
- 属性和方法
- 继承
- 多态
- 封装
- 特殊方法
- 抽象类和接口
- 组合和聚合
- 面向对象设计原则
- 最佳实践:命名规范、类设计、属性和方法设计、异常处理、测试
通过学习和掌握这些概念,可以编写出更加模块化、可维护、可扩展的Python程序。
发布网站:荣殿教程(zhangrongdian.com)
作者:张荣殿