Python装饰函数作用域

2024-09-28 01:25:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我似乎不明白为什么下面的代码没有将demovar暴露给修饰函数:

def exposebasevar(function):
    def decorator(*args, **kwargs):
        demovar = 'Where am I?' # => or MyThreadSafeObjectHandle()
        return function(*args, **kwargs)
    return decorator

@exposebasevar
def usesexposedvariable():
    print demovar # this line will give an error

usesexposedvariable()

背景:我有一个模块,每个函数都使用一个全局变量。 现在我想让这个线程安全,所以我想通过一个装饰器使这个变量可用。然后在decorator中,我可以找出对象的哪个实例属于线程并将其传入。这样我就不需要更改每个函数的签名或内容。在

有人知道怎么做吗?谢谢。在


Tags: or函数代码returndefargsfunctiondecorator
3条回答

这将是动态范围界定。被广泛认为是一个非常糟糕的想法,因此在包括Python在内的各种语言中根本不受支持。只是不可能,除非你想拉非常肮脏和脆弱的黑客。实际上,我将此作为标准免责声明包括在内,并不是因为我心里有这样的解决方案。我能提供的最接近“工作”的是重新编写字节码,呃。在

相反,让它成为修饰函数的参数。或者取消全球批发,从长远来看,这可能会更简单、更好。在

def exposebasevar(function):
    def decorator(*args, **kwargs):
        demovar = 'Where am I?'
        return function(*args, demovar=demovar, **kwargs)  # <<
    return decorator

@exposebasevar
def usesexposedvariable(demovar):  # <<
    print demovar

I have a module with one global var that is used in each and every function. Now i want to make that threadsafe ...

您所描述的基本上是^{}的目的;不幸的是,您可能需要稍微更改代码以使其工作,问题是线程本地对象本身不是线程本地的;只有它的属性才是。只要始终使用线程本地对象的属性,它几乎是透明的:

您的代码无法正常工作的原因与以下原因完全相同:

def f():
  print v   # NameError: global name 'v' is not defined

def g():
  v = 42
  f()

g()

最干净的方法可能是将demovar作为参数传递给function

^{pr2}$

相关问题 更多 >

    热门问题