6.1 类方法的装饰器
装饰器也可以用于类的方法。重要的是要记住,对于类的方法,需要正确传递 self 或 cls 参数。
关于类的细节我们还没学,不过我希望你知道装饰器有这样的功能。
def log_method_call(func):
def wrapper(self, *args, **kwargs):
print(f"调用方法 {func.__name__}")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def say_hello(self):
print("Hello from MyClass!")
obj = MyClass()
obj.say_hello()
解释
装饰器 (log_method_call): 这个装饰器接收方法 func 并返回一个新的函数 wrapper,它在调用方法前打印一条消息。
带有装饰器的方法类 (say_hello): 方法 say_hello 被装饰器 log_method_call 包裹,从而在调用时添加了额外的行为。
输出:
调用方法 say_hello
Hello from MyClass!
6.2 多个装饰器
你可以为一个函数使用多个装饰器,依次叠加。装饰器的应用顺序与声明顺序相反。
def decorator1(func):
def wrapper():
print("装饰器 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("装饰器 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
解释
装饰器 (decorator1 和 decorator2): 这些装饰器在调用函数 func 前添加自定义消息。
具有装饰器的函数 (say_hello): 函数 say_hello 被两个装饰器包裹,首先应用 decorator2,然后 decorator1。
输出:
# 装饰器 1
# 装饰器 2
Hello!
6.3 内置装饰器
Python 提供了一些内置装饰器用于标准任务,比如静态方法、类方法和属性。
@staticmethod
装饰器 @staticmethod 用于创建静态方法,该方法不需要类的实例即可调用。
class MyClass:
@staticmethod
def static_method():
print("这是一个静态方法。")
MyClass.static_method()
@classmethod
装饰器 @classmethod 用于创建类方法,该方法接受类(而不是实例)作为第一个参数。
class MyClass:
@classmethod
def class_method(cls):
print(f"这是类方法 {cls.__name__}。")
MyClass.class_method()
@property
装饰器 @property 用于创建属性的 getter、setter 和 deleter。
class MyClass:
def __init__(self, value):
self.hidden_value = value
@property
def value(self):
return self.hidden_value
@value.setter
def value(self, new_value):
self.hidden_value = new_value
obj = MyClass(10)
print(obj.value) # 输出: 10
obj.value = 20
print(obj.value) # 输出: 20
这些是内置的装饰器,Python 解释器确保它们能正确工作。
6.4 装饰器的使用示例
日志记录
装饰器可以用来记录函数和方法的调用。
def log_call(func):
def wrapper(*args, **kwargs):
print(f"调用函数 {func.__name__} 参数为 {args} 和 {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_call
def add(x, y):
return x + y
print(add(2, 3))
访问控制
装饰器可以用来控制对函数和方法的访问。
def require_authentication(func):
def wrapper(*args, **kwargs):
if not args[0].is_authenticated:
raise PermissionError("用户未经认证。")
return func(*args, **kwargs)
return wrapper
class User:
def __init__(self, is_authenticated):
self.is_authenticated = is_authenticated
@require_authentication
def view_profile(self):
print("用户资料")
user = User(is_authenticated=True)
user.view_profile() # 成功调用
user2 = User(is_authenticated=False)
user2.view_profile() # PermissionError: 用户未经认证。
缓存
装饰器可以用来缓存函数的结果。
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
GO TO FULL VERSION