Python装饰器变量访问

时间:2016-03-13 21:06:02

标签: python

我有一个装饰器函数my_fun(I,k),它会应用于函数add(x,y)

@my_fun(4,5)
def add(x,y): return x+y

我是Python的新手想知道我是否正在编写my_fun函数

  1. 如何在x,y
  2. 的添加方法中访问my_fun
  3. 如何在装饰器功能中访问add的返回值?
  4. 我对语法和概念有点困惑,任何解释都会有所帮助。

2 个答案:

答案 0 :(得分:2)

装饰器由装饰器函数和函数包装器组成(如果你想要装饰器的另外一个参数,那么它周围的另一个外层函数):

# Takes the arguments for the decorator and makes them accessible inside
def my_fun(decorator_argument1, decorator_argument2):

     # Takes the function so that it can be wrapped.
     def wrapfunc(func):

         # Here we are actually going to wrap the function ... finally
         def wrapper(*args, **kwargs):

             # Call the function with the args and kwargs
             res = func(*args, **kwargs)

             # return this result
             return res

         # Replace the decorated function with the wrapper
         return wrapper
    # Return the wrapper for the function wrapper :-)
    return wrapfunc

在您的情况下,如果您只想将装饰器与您的功能一起使用,则无需使用*args, **kwargs并将其替换为:

         def wrapper(x, y):

             # Here you can do stuff with x and y, i.e. print(x)

             # Call the function with x and y
             res = func(x, y)

             # Here you can do stuff with the result, i.e. res = res * decorator_argument1

             return res

我指出了您可以访问xy的位置以及结果。

如果要预定义xy的值,自定义装饰器不是最好的方法。您可以使用默认值:

def add(x=4,y=5): return x+y

add() # returns 9
add(2) # returns 7
add(5, 10) # returns 15

或者如果您想修复参数,则应使用functools.partial

答案 1 :(得分:0)

如果您使用@my_fun(4, 5)将参数传递给装饰器,则需要三级嵌套函数以最简单的方式实现装饰器。外层是“装饰工厂”。它返回中间级函数,装饰器。装饰器使用它作为参数装饰的函数调用,并且需要返回内部最嵌套的函数,即包装器。包装函数是用户调用的函数。

def decorator_factory(deco_arg, deco_arg2): # name this whatever you want to use with @syntax
    def decorator(func):
        def wrapper(func_arg, func_arg2):
            # This is a closure!
            # In here you can write code using the arguments from the enclosing scpoes. e.g.:
            return func(func_arg*deco_arg, func_arg2*deco_arg2) # uses args from all levels
        return wrapper
    return decorator

这里的内部功能是闭包。即使在这些范围所属的函数已经完成运行之后,它们也可以看到它们所定位的范围内的变量。

(注意,如果您希望装饰器能够装饰许多不同的功能,您可能希望wrapper功能接受*args**kwargs并将它们传递给{{ 1}}。上面的例子仅适用于接受两个参数的函数。对于某些用途,这样的限制可能是完全合理的,但并非总是如此。)