您能修改修饰函数范围内的变量吗

2024-04-25 23:25:19 发布

您现在位置: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的引用,但是我知道它必须在调用print my_var时由my_func访问。你知道吗

另外,我仍然需要每个修饰函数有一个my_var实例。你知道吗


Tags: 函数importreturnvarmydefargsdecorator
1条回答
网友
1楼 · 发布于 2024-04-25 23:25:19

作为@胡安帕.阿里维拉加如注释所示,这可以通过自由变量查找和绑定到函数闭包对象来实现,如下所示:

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

相关问题 更多 >