你能修改装饰函数范围内的变量吗?

时间:2017-11-30 23:38:26

标签: python decorator

采取以下装饰器示例:

import functools

def my_decorator( func ):
   my_var = 1

   @functools.wraps( func )
   def wrapper( *args, **kwargs ):
      print my_var
      return func( *args, **kwargs )

   return wrapper

@my_decorator
def my_func( s ):
   print s

有没有办法在全球范围内访问和修改my_var

使用globals()[ 'my_func' ]查看包装函数内部我没有看到my_var的任何引用,但我知道my_func必须可以访问它print my_var my_var 1}}。

此外,我仍然需要每个装饰函数有一个req.getSession().setAttribute(“user”, user); 个实例。

1 个答案:

答案 0 :(得分:0)

正如@ juanpa.arrivillaga在评论中所示,这可以通过自由变量查找和绑定到函数闭包对象来实现,如下所示:

i = my_func.func_code.co_freevars.index('my_var')
my_var = my_func.func_closure[i].cell_contents

发布的问题是使用不可变对象,因此无法修改my_var,也无法重新分配基础变量。这只有在my_var可变的情况下才有效。

更好的解决方案是将此变量作为包装函数中的属性包含在内,通过@functools.wraps装饰器将其与所有其他属性一起复制到包装函数。但是,它仍然需要my_var作为可变对象才能进行修改。

上面显示的例子如下:

import functools

def my_decorator( func ):
   my_var = func.my_var = {}

   @functools.wraps( func )
   def wrapper( *args, **kwargs ):
      print my_var
      return func( *args, **kwargs )

   return wrapper

@my_decorator
def my_func( s ):
   print s

my_func( "First call" )
my_func.my_var[ 'Testing' ] = '123'
my_func( "Second call" )

输出:

{}
First call
{'Testing': '123'}
Second call