1

我似乎无法弄清楚下面的代码是否没有将 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()

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

有人知道如何设置吗?谢谢。

4

3 回答 3

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
于 2013-01-05T19:25:44.647 回答
2

您的代码不起作用的原因与以下不起作用的原因完全相同:

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

def g():
  v = 42
  f()

g()

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

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

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

usesexposedvariable()
于 2013-01-05T19:25:10.937 回答
1

我有一个带有一个全局变量的模块,每个函数都使用它。现在我想让那个线程安全......

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

于 2013-01-05T19:47:53.557 回答