python装饰器详解
一、函数装饰器,装饰函数
#上面是装饰器,下面是原函数 def ifren(p): #p是额外带来的参数,因为要带参数p所以多了一层函数嵌套,如果需要给装饰器本身传递参数,可以使用一个外层函数来封装装饰器。 def plusnihao(function): def wraper(): #核心装饰器代码,function代指sayhello函数,是由上一层传入进来的,本层负责增加前后功能 function() print("and nihao") #添加的功能 print(p) #最上层传入进来的,是额外带进来的参数 return wraper #返回核心装饰器 return plusnihao #因为有参数p,再给核心装饰器装一层皮 返回 @ifren(1000) #额外的参数p。 @后面是装饰器函数名 这句话相当于 ifren(1000)(plusnihao(wraper(sayhello))) def sayhello(): print("nihao") sayhello() #用原函数运行
再一例子
def decorator(func): def wrapper(*args, **kwargs): # 参数必须和func一样,这样写全能 # 在这里添加额外的功能 print("Before calling the function") result = func(*args, **kwargs) #以前什么参数,现在原样执行 print("After calling the function") return result # 有没有返回不重要 return wrapper @decorator def my_function(a=5, b="fgh"): print(f"Hello{a}, this is my {b} function.") # 调用my_function时,实际上调用的是wrapper函数 my_function()
# 使用functools.wraps保留原函数信息 # 在使用装饰器时,原函数的元信息(如函数名、文档字符串等)会被包装函数所替代。为了保留这些信息,可以使用functools.wraps装饰器。 from functools import wraps def my_decorator(func): @wraps(func) #这个地方保留 def wrapper(*args, **kwargs): print("Something is happening before the function is called.") result = func(*args, **kwargs) print("Something is happening after the function is called.") return result return wrapper @my_decorator def example(): """This is an example function.""" print("Hello from a function.") print(example.__doc__) # 输出: This is an example function.
二、类装饰器,装饰函数
# author:baoshan # 带参数的类装饰器,和不带参数的类装饰器有很大的不同 # 类装饰器的实现,必须实现__call__和__init__两个内置函数。 # __init__:装饰器带参数时不再接收被装饰函数,而是接收传入参数;没带参数时接受函数为构造函数 # __call__:带参数时接收被装饰函数,再起一层wrapper。不带参数时接受参数*args, **kwargs参数,这时他就是wrapper。
例子:不带参数
from functools import wraps class animal: def __init__(self, func): #原函数变为类的构造函数 self.func = func # @wraps 保留函数元信息 def __call__(self, *args, **kwargs):#在Python中,__call__是一个特殊方法, #它允许一个类的实例表现得像函数一样,可以被调用。当你调用一个类的实例时,Python会自动执行该实例的__call__方法 print("working here") res = self.func(*args, **kwargs) return res @animal #类装饰器装饰函数,函数就变为了类的构造函数 def test(name, kind): word = f"{name} belongs to {kind}" return word A = test("cow", "mammals") print(type(test)) print(A)
例子:带参数
class animals: def __init__(self, prefix): self.prefix = prefix # 装饰器传入的参数变为类的属性 def __call__(self, func): # 原传入函数在call函数传入,再起一层wraooer def wrapper(*args, **kwds): # 核心装饰器,参数用通用的这个格式 print("前置功能" + self.prefix) print(func(*args, **kwds)) print("后置功能") return wrapper @animals("汪汪叫") def cat(c): print(f"叫声是{c}") cat("喵喵叫")

浙公网安备 33010602011771号