接口是一个类必须遵循的规则或约定,它定义了类应该具备哪些方法,但不提供具体的实现。在 Python 中,接口常用在规定某些类必须实现特定的方法。通过接口,不同的类可以被相同的代码调用,只要它们实现了接口的要求。
协议是 Python 中的一种接口定义方式,常用于规定一个类应该具备哪些方法。协议是“非正式”的接口,它不要求显式地继承任何东西,只需要类实现了协议中的方法。
from typing import Protocol
# 定义一个飞行协议,规定类必须有 fly 方法
class Flyer(Protocol):
def fly(self) -> None:
pass
# 定义一个 Bird 类,它实现了 fly 方法
class Bird:
def fly(self) -> None: # 注意 -> None 表示这个方法不返回任何值
print("Bird is flying")
# 定义一个 Airplane 类,它也实现了 fly 方法
class Airplane:
def fly(self) -> None:
print("Airplane is flying")
# 定义一个函数,这个函数接受任何有 fly 方法的对象
def make_fly(flyer: Flyer):
flyer.fly()
# 创建 Bird 和 Airplane 的实例,并传递给 make_fly 函数
bird = Bird()
plane = Airplane()
make_fly(bird) # 输出: Bird is flying
make_fly(plane) # 输出: Airplane is flyingFlyer 是一个协议类,它定义了所有实现此协议的类必须具备的 fly 方法。-> None 的意思是这个方法不返回任何值。None 是 Python 的一种特殊类型,表示什么都没有。Flyer 协议的对象作为参数。无论是 Bird 还是 Airplane,只要它们实现了 fly 方法,就可以传给这个函数。Bird is flying
Airplane is flying这个示例展示了 Bird 和 Airplane 类如何实现同样的 fly 方法,使得它们都可以被 make_fly 函数调用。
装饰器是 Python 中的一个强大特性,允许你在不修改原始函数的情况下,为函数添加额外的功能。装饰器本质上是一个函数,它接收另一个函数作为参数,并返回一个新的函数。
# 定义一个简单的装饰器函数
def simple_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func() # 调用原始函数
print("Something is happening after the function is called.")
return wrapper
# 使用装饰器
@simple_decorator # @符号表示我们使用simple_decorator来装饰say_hello函数
def say_hello():
print("Hello!")
# 调用被装饰的函数
say_hello()say_hello 函数传递给 simple_decorator 装饰器,相当于 say_hello = simple_decorator(say_hello)。wrapper 函数包裹了原始的 say_hello 函数,在调用 say_hello 时,会先执行 wrapper 内的代码。func 是原始的 say_hello 函数,通过调用它,我们在 wrapper 中执行了原始函数的功能。Something is happening before the function is called.
Hello!
Something is happening after the function is called.@ 符号,你需要手动将函数传给装饰器。使用 @ 符号时,装饰器会在函数定义之后立即应用,不需要手动传递。# 使用 @ 语法糖
@simple_decorator
def say_hello():
print("Hello!")
# 不使用 @ 语法糖,等同于上面的代码
def say_hello():
print("Hello!")
say_hello = simple_decorator(say_hello)上下文管理器用于在一段代码运行前后自动管理资源,比如文件、网络连接等。上下文管理器确保资源在使用后被正确释放,避免资源泄漏问题。
# 使用上下文管理器打开文件
with open('example.txt', 'w') as file:
file.write('Hello, World!')
# 这个文件会在 with 语句块结束时自动关闭你可以通过定义 __enter__ 和 __exit__ 方法来自定义上下文管理器。这两个方法分别在上下文管理器的进入和退出时执行。
class MyContextManager:
def __enter__(self):
print("Entering the context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exiting the context")
if exc_type:
print(f"Exception type: {exc_type}")
print(f"Exception value: {exc_val}")
print(f"Traceback: {exc_tb}")
return True # 处理异常后,继续执行
# 使用自定义上下文管理器
with MyContextManager():
print("Inside the context")
raise ValueError("Oops!") # 故意引发一个异常with 语句时,__enter__ 方法会被自动调用。你可以在这里做一些初始化操作。with 语句结束时,__exit__ 方法会被调用。这个方法接受三个参数:exc_type(异常类型)、exc_val(异常值)、exc_tb(异常的追踪信息)。这些参数用于处理在 with 语句块内发生的任何异常。__exit__ 返回 True,异常将被抑制,不会向外抛出。如果返回 False 或者不返回,异常将会被继续抛出。Entering the context
Inside the context
Exiting the context
Exception type: <class 'ValueError'>
Exception value: Oops!
Traceback: <traceback object at 0x...>元类是用来创建类的“类”。普通类是用来创建对象的,而元类是用来创建类的。元类通常用于自动修改类的定义或行为。
class MyMeta(type):
def __new__(cls, name, bases, dct):
print(f"Creating class {name}")
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=MyMeta):
pass
# 创建 MyClass 的实例
obj = MyClass()type 是 Python 内置的元类,用于创建所有的类。MyMeta 继承自 type,我们通过 __new__ 方法来控制类的创建。__new__ 是一个特殊的方法,它在 __init__ 之前被调用,用于创建类。cls 是元类本身,name 是类的名称,bases 是类的基类(父类),dct 是类的属性和方法的字典。MyClass 时,Python 会使用 MyMeta 元类来创建 MyClass 类。Creating class MyClass当你定义 MyClass 时,会输出 Creating class MyClass,表示元类 MyMeta 正在创建 MyClass。
SOLID 是面向对象设计的五大原则,用来编写可维护、可扩展的代码。我们一条一条来看。
单一职责原则(Single Responsibility Principle)要求一个类应该只负责一件事。这样可以让类更简单、更易维护。
class ReportGenerator:
def generate(self):
print("Generating report")
class ReportSaver:
def save(self):
print("Saving report")ReportGenerator 负责生成报告。ReportSaver 负责保存报告。每个类都有明确的职责,不会混在一起。开放/封闭原则(Open/Closed Principle)要求软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。
class Shape:
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * (self.radius ** 2)
class Rectangle(Shape):
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.widthShape 类,我们可以创建新的形状类,而不需要修改现有代码。里氏替换原则(Liskov Substitution Principle)要求子类对象必须能够替换基类对象,而不会影响程序的正确性。
class Bird:
def fly(self):
print("Bird is flying")
class Penguin(Bird):
def fly(self):
raise NotImplementedError("Penguins cannot fly")
# 这种设计违反了里氏替换原则,因为企鹅不能飞,但它继承了能飞的鸟类Penguin 不能替代 Bird,因为企鹅不会飞,这违反了里氏替换原则。接口隔离原则(Interface Segregation Principle)要求类不应该被强迫实现它不需要的接口或方法。
class Workable:
def work(self):
pass
class Eatable:
def eat(self):
pass
class Worker(Workable, Eatable):
def work(self):
print("Working")
def eat(self):
print("Eating")
class Robot(Workable):
def work(self):
print("Working")
# Robot 只实现了它需要的接口,而不是所有接口Robot 只实现了 Workable 接口,而不需要实现 Eatable 接口。依赖倒置原则(Dependency Inversion Principle)要求高层模块不应该依赖于低层模块,而应该依赖于抽象(接口)。
class Keyboard:
def type(self):
return "Typing"
class Monitor:
def display(self):
return "Displaying"
class Computer:
def __init__(self, keyboard: Keyboard, monitor: Monitor):
self.keyboard = keyboard
self.monitor = monitor
def operate(self):
print(self.keyboard.type())
print(self.monitor.display())Computer 依赖于 Keyboard 和 Monitor 抽象,而不是它们的具体实现,这使得更换这些组件变得容易。以上就是关于【Python篇】Python 类和对象:详细讲解(下篇)的内容啦,各位大佬有什么问题欢迎在评论区指正,您的支持是我创作的最大动力!❤️