1. 什么是装饰器?
所谓装饰器可以理解为一种特殊的函数,就是把函数包装一下,为函数添加一些附加功能,装饰器就是一个函数,参数为被包装的函数,返回包装后的函数。
2.常见的装饰器
2.1 @classmethod (内置装饰器)
2.2 @staticmethod (内置装饰器)
2.3 @property (内置装饰器)
2.4 @app (框架提供的装饰器)
2.1 @classmethod
类方法
作用:是一种特殊的方法,可以在不创建类实例的情况下调用,用于定义类方法。
定义:
class Testclassmethod:
@classmethod
def test(cls,arg1,arg2):
pass
#要想调用这个类方法的话,就直接Testclassmethod.test()调用
应用场景:
参考链接:解锁 Python 类方法的精髓:@classmethod 的应用技巧!
2.2.1 替代构造函数
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_birth_year(cls, name, birth_year):
age = 2024 - birth_year
return cls(name, age)
person = Person.from_birth_year("Alice", 1990)
print(person.name, person.age) # 输出:Alice 34
2.2.2 实现工厂模式
工厂模式:是一种设计模式,目的是简化对象的创建过程。不需要自己去处理复杂的细节。
class Car:
def drive(self):
pass
class Sedan(Car):
def drive(self):
print("Driving a sedan")
class SUV(Car):
def drive(self):
print("Driving an SUV")
class Hatchback(Car):
def drive(self):
print("Driving a hatchback")
class CarFactory:
@classmethod
def create_car(cls, car_type):
if car_type == 'sedan':
return Sedan()
elif car_type == 'suv':
return SUV()
elif car_type == 'hatchback':
return Hatchback()
else:
raise ValueError("Invalid car type")
# 使用工厂模式创建汽车对象
if __name__ == "__main__":
# 获取用户输入的车型
car_type = input("Enter the car type (sedan, suv, hatchback): ")
# 通过工厂创建汽车
car = CarFactory.create_car(car_type)
# 调用汽车的 drive 方法
car.drive()
2.2.3 实现单例模式
单例模式:也是一种设计模式,目的是在整个程序运行期间,只允许一个类有一个实例存在,并且提供一个全局访问点来获取这个实例。
class Logger:
_instance = None # 用于存储单例实例
def __init__(self):
self.log_messages = []
def log_message(self, message):
self.log_messages.append(message)
def display_logs(self):
for message in self.log_messages:
print(message)
@classmethod
def get_instance(cls):
if cls._instance is None:
cls._instance = cls()
return cls._instance
# 使用单例模式创建Logger实例
if __name__ == "__main__":
# 第一次获取Logger实例
logger1 = Logger.get_instance()
logger1.log_message("First message.")
# 第二次获取Logger实例
logger2 = Logger.get_instance()
logger2.log_message("Second message.")
# 验证两个实例是否相同
print("Are logger1 and logger2 the same instance?", logger1 is logger2)
# 显示所有日志
logger1.display_logs()
2.2 @staticmethod
静态方法
静态方法和类方法十分相似,但是在用法上有轻微的区别,
classmethod必须将类对象的引用作为第一个参数,而staticmethod可以不带任何参数。
由于这个差别,所以二者的适用场景不一样。
因为静态方法与类方法本身没有直接关联,所以更像是类中的一个普通函数,静态方法不会自动接受任何特殊参数,因为静态方法不知道类的状态,例如不可以修改类变量。所以常用于执行与类的实例无关的操作。
类方法是与类关联的方法,可接受一个名为cls的参数,约定俗称写cls,其实可以是任何名字,这个参数表示当前类备色,类方法可以访问和修改类状态,即可以访问和修改类变量。
2.2.1 静态方法例子
class MathUtil:
@staticmethod
def add_numbers(a, b):
"""静态方法,用于计算两个数字的和"""
return a + b
# 使用静态方法
if __name__ == "__main__":
num1 = float(input("Enter the first number: "))
num2 = float(input("Enter the second number: "))
result = MathUtil.add_numbers(num1, num2)
print(f"The sum of {num1} and {num2} is {result}")
2.3 @property
作用:允许将一个方法定义为类的一个属性来使用(rect.area),而不是像通常那样作为一个方法调用(rect.area())
这样的好处是可以在不改变调用方式的情况下,为读取,设置或删除类的属性提供灵活性,同时可以对这些操作进行控制。
下面举个例子,来验证@property的优势、
- 没有使用property的例子:
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
def get_celsius(self):
return self._celsius
def set_celsius(self, value):
if value < -273.15:
raise ValueError("Temperature below -273.15 is not possible.")
self._celsius = value
temp = Temperature(25)
# 获取温度
print(temp.get_celsius()) # 输出: 25
# 设置温度
try:
temp.set_celsius(-300)
except ValueError as e:
print(e) # 输出: Temperature below -273.15 is not possible.
- 使用property的例子
class Temperature:
def __init__(self, celsius):
self.celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Temperature below -273.15 is not possible.")
self._celsius = value
temp = Temperature(25)
# 获取温度
print(temp.celsius) # 输出: 25
# 设置温度
try:
temp.celsius = -300
except ValueError as e:
print(e) # 输出: Temperature b
对比分析
代码简洁性:在使用 @property 的版本中,我们可以直接使用 temp.celsius 来获取和设置温度值,而不需要调用方法。
可读性和可维护性:使用 @property 的代码更加直观,更容易理解。
封装性:即使我们使用了 @property,外部代码仍然不能直接访问 _celsius 这个私有变量,从而保证了数据的安全性。
动态性:使用 @property 可以让我们更容易地改变属性的行为,例如增加更多的逻辑或改变数据存储的方式,而无需更改客户端代码。
- 其他例子:
展示了如何使用 @property 来定义一个 getter 方法
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@property
def age(self):
"""Getter for the age attribute."""
return self._age
@age.setter
def age(self, value):
"""Setter for the age attribute with validation."""
if value < 0:
raise ValueError("Age cannot be negative.")
self._age = value
# 创建一个 Person 实例
person = Person("Alice", 30)
# 使用 getter 方法来获取 age 属性的值
print(person.age) # 输出: 30
# 使用 setter 方法来设置 age 属性的值
person.age = 35
print(person.age) # 输出: 35
# 尝试设置一个非法的 age 值
try:
person.age = -5
except ValueError as e:
print(e) # 输出: Age cannot be negative.
2.4 @app
FastAPI 是一个现代的、快速(高性能)的 web 框架,用于构建 APIs。它基于 Python 3.7+ 的标准库,并且利用了 starlette 和 pydantic。FastAPI 提供了许多装饰器来帮助你定义路由和处理 HTTP 请求。
FastAPI 中常用的装饰器。
@app.get: 用于定义 GET 请求的路由。
@app.post: 用于定义 POST 请求的路由。
@app.put: 用于定义 PUT 请求的路由。
@app.delete: 用于定义 DELETE 请求的路由。
@app.patch: 用于定义 PATCH 请求的路由。
@app.options: 用于定义 OPTIONS 请求的路由
各位看官,如果看完感觉有一点点收获的话,可以给点打赏哟。失业创作不易(/(ㄒoㄒ)/~~)