Python装饰函数作用域

Python装饰函数作用域,python,multithreading,decorator,scoping,Python,Multithreading,Decorator,Scoping,我似乎不知道下面的代码是否没有将demovar公开给修饰函数: def exposebasevar(function): def decorator(*args, **kwargs): demovar = 'Where am I?' # => or MyThreadSafeObjectHandle() return function(*args, **kwargs) return decorator @exposebasevar def u

我似乎不知道下面的代码是否没有将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中,我可以找出对象的哪个实例属于线程,并将其传入。这样我就不需要更改每个函数的签名或内容


有人知道怎么设置吗?谢谢。

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

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

def g():
  v = 42
  f()

g()
最干净的方法可能是将
demovar
作为参数传递给
函数

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()

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

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

def g():
  v = 42
  f()

g()
最干净的方法可能是将
demovar
作为参数传递给
函数

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()

这将是动态范围界定。人们普遍认为这是一个非常糟糕的想法,因此在包括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
def exposebasevar(函数):
def装饰器(*args,**kwargs):
德莫瓦尔=‘我在哪里?’

返回函数(*args,demovar=demovar,**kwargs)#这将是动态作用域。人们普遍认为这是一个非常糟糕的想法,因此在包括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
def exposebasevar(函数):
def装饰器(*args,**kwargs):
德莫瓦尔=‘我在哪里?’
返回函数(*args,demovar=demovar,**kwargs)#
我有一个模块,每个函数都使用一个全局变量。现在我想让那个线程安全

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

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


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

欢迎使用StackOverflow!为什么您希望这段代码使demovar对函数可用?为什么不将demovar作为参数传递给函数呢?值得注意的是,无论您在哪里进行这种包装,都可以使用它。欢迎使用StackOverflow!为什么您希望这段代码使demovar对函数可用?为什么不直接将demovar作为参数传递给函数呢?值得注意的是,无论你在哪里进行这种包装,使用它都是一个好主意。谢谢,我知道它有点粗糙。。。然后,当每个文件中的每个函数都需要第一个参数来传递作用域时,有些东西告诉我应该自动执行。@user1951656是的,您可以自动执行tjat。使用
sed
或重构工具;-)它还有一个额外的好处,那就是它不会产生运行时成本,也不是需要破译才能理解代码的魔法。。。然后,当每个文件中的每个函数都需要第一个参数来传递作用域时,有些东西告诉我应该自动执行。@user1951656是的,您可以自动执行tjat。使用
sed
或重构工具;-)它还有一个额外的好处,那就是它不产生运行时成本,也不是为了理解代码而必须破译的魔法。谢谢。我将使用Flask框架的方法,使全局变量成为真实对象的代理对象,将其作为真实对象,然后在每次访问时使用基于线程id的dict快速偷偷地查找代理对象。不知何故,这也给了我一种非常棘手的解决方法。。。基本上,唯一的“非黑客”方法就是将te参数(例如“请求”)传递给每个请求处理程序,这是非常可行的。只是有点。。。不优雅。。。我希望我能自动实现这一点,或者以某种方式将其传递给函数访问的函数“globals”。其他想法仍然欢迎:)谢谢。我将使用Flask框架的方法,使全局变量成为真实对象的代理对象,将其作为真实对象,然后在每次访问时使用基于线程id的dict快速偷偷地查找代理对象。不知何故,这也给了我一种非常棘手的解决方法。。。基本上,唯一的“非黑客”方法就是将te参数(例如“请求”)传递给每个请求处理程序,这是非常可行的。只是有点。。。不优雅。。。我希望我能自动实现这一点,或者以某种方式将其传递给函数访问的函数“globals”。其他想法仍然受欢迎:)