当前位置: 首页 > 后端技术 > Python

终于弄明白了Python的装饰器(二)

时间:2023-03-26 18:25:00 Python

本系列文档:1.终于弄清楚了Python的装饰器(一)2.终于弄明白了Python的装饰器(二)3.终于弄明白了Python的装饰器(三)4.终于弄明白了Python的装饰器(四)2.装饰器的高级用法给装饰函数传参#不是黑魔法,只是为了包装(wrapper)):print("Igotargs!Look:{0},{1}".format(arg1,arg2))function_to_decorate(arg1,arg2)return_arguacptings#因为当你调用装饰器返回的函数时,包装器被调用,将参数传递给包装器包装的函数@a_decorator_passing_argumentsdefprint_full_name(first_name,last_name):print("Mynameis{0}{1}".format(first_name,last_name))print_full_name("Peter","Venkman")#输出:#Igotargs!看:PeterVenkman#我叫PeterVenkman向装饰器传递参数关于向装饰器传递参数设备本身,你怎么看?这可能很尴尬,因为装饰器必须接受一个函数作为参数。因此,您不能将装饰函数的参数直接传递给装饰器。在寻找解决方案之前,让我们写一些提示:#decoratorsareordinaryfunctionsdefmy_decorator(func):print("Iamanordinaryfunction")defwrapper():print("Iamfunctionreturnedbythedecorator")func()returnwrapper#因此,你可以不带“@”调用它deflazy_function():print("zzzzzzzzz")decorated_function=my_decorator(lazy_function)#Output:Iamanordinaryfunction#输出“Iamanordinaryfunctionam一个普通函数”,因为你只是调用了装饰器,而不是函数:#这里没有魔法,使用'@'@my_decoratordeflazy_function():print("zzzzzzzzz")#outputs:Iamanordinaryfunctionresultsinthe相同的。my_decorator”被调用了。所以当你使用@my_decorator时,你告诉Python通过变量调用my_decorator标记的函数。defdecorator_maker():print("我做装饰器!我只执行一次:""当你让我创建一个装饰器时。")defmy_decorator(func):print("我是一个装饰器!我只在你创建时执行装饰一个函数。")defwrapped():print("我是被装饰函数的包装器。""当你调用被装饰函数时我被调用。""作为包装器,我返回被装饰函数的结果。")returnfunc()print("作为装饰器,我返回包装函数。")returnwrappedprint("作为装饰器制造商,我返回一个装饰器")returnmy_decorator#让我们新建一个装饰器new_decorator=decorator_maker()#输出:#我做装饰器!我只执行一次:当你让我创建一个装饰器时。#作为装饰器制造者,我返回一个装饰器#让我们装饰这个函数defdecorated_function():print("我是装饰函数。")decorated_function=new_decorator(decorated_function)#Output:#我是装饰师!我仅在装饰函数时执行。#作为装饰器,我返回包装函数#让我们调用此函数decorated_function()#Output:#Iamthewrapperaroundthedecoratedfunction.当您调用装饰函数时,我会被调用。#作为包装器,我返回修饰函数的结果。#我是装饰函数。不出意外,和我们之前演示的内容一样让我们再做一次完全一样的事情,但是这次我们跳过了所有讨厌的中间变量:defdecorated_function():print("Iamthedecoratedfunction.")decorated_function=decorator_maker()(decorated_function)#输出:#我做装饰器!我只被执行一次:当你让我创建一个装饰器时。#作为一个装饰器制造者,我返回一个装饰器#我是一个装饰器!只有当你装饰一个函数时,我才会被执行。#作为装饰者,我返回被包装的函数。#最后:decorated_function()#输出:#我是被装饰函数的包装器。当你调用装饰函数时我被调用。#作为包装器,我返回装饰函数的结果。#我是装饰函数。让我们把它变的更精简:@decorator_maker()defdecorated_function():print(“我是装饰函数。”)#输出:#我制作装饰器!我只被执行一次:当你让我创建一个装饰器时。#作为一个装饰器制造者,我返回一个装饰器#我是一个装饰器!只有当你装饰一个函数时,我才会被执行。#作为装饰者,我返回包装好的function.#Finally:decorated_function()#Output:#I是装饰函数的包装器。当你调用装饰函数时我被调用。#作为包装器,我返回装饰函数的结果。#我是装饰函数。嘿,你看到了吗?我们使用了带有“@”语法的函数调用!那么,回到带有参数的装饰器如果我们可以使用一个函数动态生成一个装饰器,我们就可以将参数传递给函数,对吧?defdecorator_maker_with_arguments(decorator_arg1,decorator_arg2):print("Imakedecorators!AndIacceptarguments:{0},{1}".format(decorator_arg1,decorator_arg2))defmy_decorator(func):#这里传递的参数是闭包.#如果你对数据包不满意,你可以忽略它。print("我是装饰器。不知何故你传给我参数:{0},{1}".format(decorator_arg1,decorator_arg2))#不要混装装饰器参数和函数参数!defwrapped(function_arg1,function_arg2):print("我是装饰函数的包装器。\n""我可以访问所有变量\n""\t-来自装饰器:{0}{1}\n""\t-来自函数调用:{2}{3}\n""然后我可以将它们传递给装饰函数".format(decorator_arg1,decorator_arg2,function_arg1,function_arg2))returnfunc(function_arg1,function_arg2)returnwrappedreturnmy_decorator@decorator_maker_with_arguments("Leonard","Sheldon")defdecorated_function_with_arguments(function_arg1,function_arg2):print("我是装饰函数,只知道我的参数:{0}""{1}".format(function_arg1,function_arg2))decorated_function_with_arguments("Rajesh","Howard")#输出:#我制作装饰器!我接受争论:LeonardSheldon#Iamthedecorator。你以某种方式向我传递了参数:LeonardSheldon#Iamthewrapperaroundthedecoratedfunction.#Icanaccessallthevariables#-fromthedecorator:LeonardSheldon#-来自函数调用:RajeshHoward#ThenIcanpassthemtothedecoratedfunction#Iamthedecoratedfunctionandonlyknowsaboutmyarguments:RajeshHoward记住它:带参数的装饰器,可以将变量作参数:c1="Penny"c2="Leslie"@decorator_maker_with_arguments("Leonard",c1)defdecorated_function_with_arguments(function_arg1,function_arg2):print("Iamthedecoratedfunction并且只知道我的参数:""{0}{1}".format(function_arg1,function_arg2))decorated_function_with_arguments(c2,"Howard")#输出:#我制作装饰器!我接受争论:LeonardPenny#Iamthedecorator。你以某种方式向我传递了论点:LeonardPenny#Iamthe装饰函数的包装器。#Icanaccessallthevariables#-fromthedecorator:LeonardPenny#-来自函数调用:LeslieHoward#ThenIcanpassthemtothedecoratedfunction#Iamthedecoratedfunctionandonlyknowaboutmyarguments:LeslieHowardAs你可以看到,你可以将参数传递给装饰器,就像任何函数传递参数一样。如果你愿意,你甚至可以使用*args,**kwargs。但请记住,装饰器仅在Python导入脚本时被调用一次。之后,您将无法动态设置参数。当你执行“importx”时,这个函数已经被装饰了,所以你不能改变任何东西。