装饰器是一个函数,它接受一个函数作为参数,并返回一个新的函数。装饰器可以用于在函数调用前后添加额外的功能,或者修改函数的行为。
装饰器通常通过在函数定义前使用@decorator_name语法来应用。
- def 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
-
- @decorator
- def say_hello():
- print("Hello!")
-
- say_hello()
输出结果:
- Something is happening before the function is called.
- Hello!
- Something is happening after the function is called.
一个简单的装饰器如下:
- def my_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
这个装饰器函数my_decorator接受一个函数func作为参数,并返回一个包装函数wrapper。在包装函数中,首先打印一条消息,然后调用传入的函数,最后再打印一条消息。
可以使用@my_decorator语法来应用这个装饰器:
- @my_decorator
- def say_hello():
- print("Hello!")
-
- say_hello()
这等价于:
- def say_hello():
- print("Hello!")
-
- say_hello = my_decorator(say_hello)
- say_hello()
可以将多个装饰器应用于同一个函数,这称为装饰器的嵌套。装饰器的应用顺序是自下而上的,即最内层的装饰器最先应用。
- def decorator1(func):
- def wrapper():
- print("Decorator 1")
- func()
- return wrapper
-
- def decorator2(func):
- def wrapper():
- print("Decorator 2")
- func()
- return wrapper
-
- @decorator1
- @decorator2
- def say_hello():
- print("Hello!")
-
- say_hello()
输出结果:
- Decorator 1
- Decorator 2
- Hello!
装饰器本身也可以接受参数。为了实现这一点,我们需要再嵌套一层函数。
- def repeat(num):
- def decorator(func):
- def wrapper(*args, **kwargs):
- for _ in range(num):
- func(*args, **kwargs)
- return wrapper
- return decorator
可以传递参数来控制装饰器的行为:
- @repeat(3)
- def say_hello():
- print("Hello!")
-
- say_hello()
输出结果:
- Hello!
- Hello!
- Hello!
除了函数装饰器,Python还支持类装饰器。类装饰器是一个实现了__call__方法的类,这样的类可以像函数一样调用。
- class MyDecorator:
- def __init__(self, func):
- self.func = func
-
- def __call__(self, *args, **kwargs):
- print("Something is happening before the function is called.")
- self.func(*args, **kwargs)
- print("Something is happening after the function is called.")
- @MyDecorator
- def say_hello():
- print("Hello!")
-
- say_hello()
输出结果:
- Something is happening before the function is called.
- Hello!
- Something is happening after the function is called.
Python提供了一些内置的装饰器,如@staticmethod、@classmethod和@property。这些装饰器常用于类的方法定义。
@staticmethod用于定义静态方法,静态方法不需要访问类或实例的属性和方法。
- class MyClass:
- @staticmethod
- def static_method():
- print("This is a static method.")
-
- MyClass.static_method()
@classmethod用于定义类方法,类方法的第一个参数是类本身(通常命名为cls)。
- class MyClass:
- @classmethod
- def class_method(cls):
- print(f"This is a class method of {cls}.")
-
- MyClass.class_method()
@property用于将方法转换为属性,以便通过属性访问方法的结果。
- class MyClass:
- def __init__(self, value):
- self._value = value
-
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, value):
- self._value = value
-
- obj = MyClass(42)
- print(obj.value) # 输出: 42
- obj.value = 99
- print(obj.value) # 输出: 99
装饰器在实际编程中有很多应用场景,下面我们列举一些常见的例子。
装饰器可以用于记录函数的调用情况。
- def log(func):
- def wrapper(*args, **kwargs):
- print(f"Calling function {func.__name__}")
- result = func(*args, **kwargs)
- print(f"Function {func.__name__} finished")
- return result
- return wrapper
-
- @log
- def say_hello():
- print("Hello!")
-
- say_hello()
输出结果:
- Calling function say_hello
- Hello!
- Function say_hello finished
装饰器可以用于检查用户是否有权限执行某个操作。
- def requires_permission(permission):
- def decorator(func):
- def wrapper(user, *args, **kwargs):
- if user.has_permission(permission):
- return func(user, *args, **kwargs)
- else:
- print(f"User {user.name} does not have {permission} permission.")
- return wrapper
- return decorator
-
- class User:
- def __init__(self, name, permissions):
- self.name = name
- self.permissions = permissions
-
- def has_permission(self, permission):
- return permission in self.permissions
-
- @requires_permission("admin")
- def delete_user(user):
- print(f"User {user.name} deleted.")
-
- admin_user = User("Admin", ["admin"])
- normal_user = User("User", [])
-
- delete_user(admin_user) # 输出: User Admin deleted.
- delete_user(normal_user) # 输出: User User does not have admin permission.
装饰器可以用于缓存函数的返回结果,以提高性能。
- def cache(func):
- memo = {}
- def wrapper(*args):
- if args in memo:
- return memo[args]
- result = func(*args)
- memo[args] = result
- return result
- return wrapper
-
- @cache
- def fibonacci(n):
- if n < 2:
- return n
- return fibonacci(n-1) + fibonacci(n-2)
-
- print(fibonacci(30)) # 输出: 832040
装饰器可以用于测量函数的执行时间。
- import time
-
- def timer(func):
- def wrapper(*args, **kwargs):
- start_time = time.time()
- result = func(*args, **kwargs)
- end_time = time.time()
- print(f"Function {func.__name__} took {end_time - start_time:.4f} seconds")
- return result
- return wrapper
-
- @timer
- def long_running_function():
- time.sleep(2)
-
- long_running_function() # 输出: Function long_running_function took 2.0001 seconds
装饰器可以用于验证函数参数的有效性。
- def validate_args(func):
- def wrapper(*args, **kwargs):
- if any(arg < 0 for arg in args):
- raise ValueError("Arguments must be non-negative")
- return func(*args, **kwargs)
- return wrapper
-
- @validate_args
- def add(a, b):
- return a + b
-
- print(add(3, 5)) # 输出: 8
- # print(add(-1, 5)) # 抛出异常: ValueError: Arguments must be non-negative
