python装饰器详解(四)---把参数传递给装饰器

因为装饰器必须接收一个函数当做参数,所以不可以直接把被装饰函数的参数传递给装饰器.

装饰器就是一个普通的函数,回顾

def my_decorator(func):
   
print("I am an ordinary function")
   
def wrapper():
       
print("I am function returned by thedecorator")
       
func()
    return wrapper

因此,同样可以像普通函数一样调用装饰器,而不用@

def lazy_function():

    print("zzzzz")

调用,

decorated_function =my_decorator(lazy_function)  ##后面加()就会输出整个装饰完的结果

输出

I am an ordinaryfunction


执行下面的代码段:

@my_decorator
def lazy_function():

    print("zzzzz")


同样输出

I am an ordinaryfunction


    和"my_decorator"一样只是被调用.所以当你@my_decorator你只是告诉Python去掉用被变量my_decorator标记的函数.并没有调用要装饰的函数。

切记:标记能直接指向装饰器.

再看下面的例子:

def decorator_maker():
   
print("I make decorators! I am excuted only once:whenyou make me create a decorator.")

   
def my_decorator(func):
       
print("I am a decorator! I am executed only whenyou decorate a function.")
       
def wrapped():
           
print("I am the wrapper around the decoratedfunction.I am called when you callthe decorated function,As the wrapper, I return the result of the decoratedfunction!")
           
return func()
       
print("As the decorator,I return the wrappedfunction")
       
return wrapped
   
print("Asthe decorator maker , I return a decorator")
   
return my_decorator

建一个装饰器,它只是一个新函数

new_decorator =decorator_maker()   #返回一个装饰器函数

输出

#I make decorators! Iam executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator

下面来装饰一个函数

def decorated_function():
   
print("I am the decorated_function")

decoration_function =new_decorator(decorated_function)   #decorator_maker返回了装饰器函数,这里加上括号及参数相当于调用了装饰器函数,执行了my_decorator(func),并未装饰,返回装饰器,就像本文开始的调用一样。

输出

#I am a decorator! Iam executed only when you decorate a function.

#As the decorator, I return the wrapped function


下面执行装饰器函数

decoration_function() #上面的装饰器函数返回了装饰器,这里加上括号才执行了装饰器

输出

#I am the wrapperaround the decorated function. I am called when you call the decoratedfunction.
#As the wrapper, I return the RESULT of the decorated function.
#I am the decorated function.

注意上述红色字体的解释部分!!

去掉上述过程中的中间变量,

def decorated_function():
   
print("I am the decorated_function")


decorated_function = decorator_maker()(decorated_function)

此时输出

#I make decorators! I am executed onlyonce: when you make me create a decorator.

#As a decorator maker, I return a decorator

#I am a decorator! I am executed only whenyou decorate a function.

#As the decorator, I return the wrappedfunction.

最后再次调用得到的函数

decorated_function()

输出

#I am the wrapper around the decoratedfunction. I am called when you call the decorated function.

#As the wrapper, I return the RESULT of thedecorated function.

#I am the decorated function.


简化一下:

@decorator_maker()   ###加括号的
def decorated_function():

    print("Iam the decorated_function")


执行上述代码段,输出

#I make decorators! I am executed onlyonce: when you make me create a decorator.

#As a decorator maker, I return a decorator

#I am a decorator! I am executed only whenyou decorate a function.

#As the decorator, I return the wrappedfunction.


最终,执行

decorated_function()

输出

#I am the wrapper around the decoratedfunction. I am called when you call the decorated function.

#As the wrapper, I return the RESULT of thedecorated function.

#I am the decorated function.


所以装饰器的参数问题可以通过上述思路解决!

def decorator_maker_arguments(decorator_arg1,decorator_arg2):
 
  print("Imake decorators!And I accept argument:",decorator_arg1,decorator_arg2)
   
def my_decorator(func):
       
# 这里传递参数的能力是借鉴了 closures.
       
# 如果对closures感到困惑可以看看下面这个:
       
#http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-python
       
print("Iam the decorator. somehow you pass me arguments:",decorator_arg1,decorator_arg2)

       
# 不要忘了装饰器参数和函数参数!
       
def wrapped(function_arg1,function_arg2):
           
print("Iam the wrapper around the decorated function.\nI can access all thevariables\n\t-fromthe decorator:{0}{1}\n\t-fromthe function call:{2}{3}\nThen I can pass them to the decorated function".format(decorator_arg1,decorator_arg2,function_arg1,function_arg2))
           
return func(function_arg1,function_arg2)
       
return wrapped
   
return my_decorator


@decorator_maker_arguments("Leonard","Sheldon")
defdecorated_function_with_arguments(function_arg1,function_arg2):
   
print("I am the decoratedfunction and only knows about my arguments: {0}{1}".format(function_arg1,function_arg2))


执行

decorated_function_with_arguments("Rajesh","Howard")


输出

#I make decorators! And I accept arguments:Leonard Sheldon

#I am the decorator. Somehow you passed mearguments: Leonard Sheldon

#I am the wrapper around the decoratedfunction.

#I can access all the variables

#   - from thedecorator: Leonard Sheldon

#   - from the functioncall: Rajesh Howard

#Then I can pass them tothe decorated function

#I am the decorated function and only knows about my arguments: Rajesh Howard


上面就是带参数的装饰器.参数可以设置成变量:

c1 = "Penny"
c2 = "Leslie"
@decorator_maker_arguments("Leonard",c1)
def decorated_function_with_arguments(function_arg1,function_arg2):
    print("I am the decorated function and only knows about my arguments: {0}{1}".format(function_arg1,function_arg2))

decorated_function_with_arguments(c2,"Howard")

#输出:

#I make decorators! And I accept arguments:Leonard Penny

#I am the decorator. Somehow you passed mearguments: Leonard Penny

#I am the wrapper around the decoratedfunction.

#I can access all the variables

#   -from the decorator: Leonard Penny

#   -from the function call: Leslie Howard

#Then I can pass them to the decoratedfunction

#I am the decorated function and only knowsabout my arguments: Leslie Howard


    可以用这种方式把任何函数的参数传递给装饰器.还可以用*args,**kwargs.

    但是一定要记住了装饰器只能被调用一次.

    当Python载入脚本后,就不可以动态的设置参数了.当你运行import x,函数已经被装饰,所以你什么都不能动了.











猜你喜欢

转载自blog.csdn.net/myordry/article/details/80694577
今日推荐