装饰器(Decorators)
装饰器是 Python 中的一种高级功能,用于动态地修改函数或类的行为。
装饰器实际上是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。
装饰器的工作原理示意图
装饰器的语法为 @decorator_name ,写在函数或方法前。
Python 还提供了一些内置的装饰器,如 @staticmethod 和 @classmethod 用于定义静态方法和类方法。
基本语法
def deco ( func ):
def wrapper ():
print ( "在原函数之前执行" )
func ()
print ( "在原函数之后执行" )
return wrapper
@deco
def hello ():
print ( "Hello!" )
hello ()
deco 是一个装饰器函数,它接受 hello 函数作为参数,并返回 wrapper 函数。
@deco 将 hello 替换为 wrapper 函数。
使用装饰器后再调用 hello() 等价于 deco(hello)()。
带参数的装饰器
分两种情况。
原函数带参数
def deco ( func ):
def wrapper ( * args , ** kwargs ):
print ( "在原函数之前执行" )
func ( * args , ** kwargs )
print ( "在原函数之后执行" )
return wrapper
@deco
def greet ( s1 , s2 ):
print ( s1 , s2 )
greet ( "Hello" , "World" )
Output 在原函数之前执行
Hello World
在原函数之后执行
这里 wrapper 函数的参数用 (*args, **kwargs) 来保持对不同函数的通用性。
装饰器函数带参数
def repeat ( times ):
def deco ( func ):
def wrapper ( * args , ** kwargs ):
for _ in range ( times ):
func ( * args , ** kwargs )
return wrapper
return deco
@repeat ( 3 )
def greet ( s1 , s2 ):
print ( s1 , s2 )
greet ( "Hello" , "World" )
Output Hello World
Hello World
Hello World
repeat 函数是一个**装饰器工厂**,它接受一个参数 times,返回一个装饰器 decorator (这就是多出来的一层函数)。
decorator 接受一个函数 func,并返回一个 wrapper 函数。
wrapper 函数会调用 func 函数 times 次。
使用 @repeat(3) 装饰 greet 函数后,调用 greet 会打印三次。
类装饰器
除了函数装饰器,Python 还支持类装饰器。类装饰器是包含 call 方法(每次调用装饰后函数时的行为)的类,它接受一个函数作为参数,并返回一个新的函数。
def my_decorator ( cls ):
class Wrapper :
def __init__ ( self , * args , ** kwargs ):
self . wrapped = cls ( * args , ** kwargs )
def display ( self ):
print ( "在类方法之前执行" )
self . wrapped . display ()
print ( "在类方法之后执行" )
return Wrapper
@my_decorator
class MyClass :
def display ( self ):
print ( "这是 MyClass 的 display 方法" )
obj = MyClass ()
obj . display ()
Output 在类方法之前执行
这是 MyClass 的 display 方法
在类方法之后执行
内置装饰器
Python 提供了一些内置的装饰器,例如:
@staticmethod : 将方法定义为静态方法,不需要实例化类即可调用。
@classmethod : 将方法定义为类方法,第一个参数是类本身(通常命名为 cls)。
@property : 将方法转换为属性,使其可以像属性一样访问。
实例:
class MyClass :
@staticmethod
def static_method ():
print ( "This is a static method." )
@classmethod
def class_method ( cls ):
print ( f "This is a class method of { cls . __name__ } ." )
@property
def name ( self ):
return self . _name
@name . setter
def name ( self , value ):
self . _name = value
# 使用
MyClass . static_method ()
MyClass . class_method ()
obj = MyClass ()
obj . name = "Alice"
print ( obj . name )
多个装饰器的堆叠
你可以将多个装饰器堆叠在一起,它们会按照从下到上的顺序依次应用。
实例:
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 ()
Output Decorator 1
Decorator 2
Hello!