0

我有一个设置name变量的方法,但它global name的第一行没有,它使用局部name变量,所以它永远不会改变全局name变量。有没有办法通过装饰set_name强制它使用 global name

name = "John"

def set_name():
    name = "Sara"

def print_name():
    global name
    print(name)

def decorator(func):
    def wrapper(*args, **kwargs):
        ## Problem:
        # Force set_name to use global 'name'
        func(*args, **kwargs)

    return wrapper

print_name()
#Output: John

decorator(set_name)()

print_name()
# Prints John, but I want to prints Sara
4

5 回答 5

2

不,除非装饰器获取函数的代码(来自函数代码对象的字节码,或使用 的源代码inspect),更改它,从更改的代码创建一个新的代码对象并用它替换函数的代码。当然,这是非常不可靠的、骇人听闻的、特定于实现的和深奥的黑魔法。只需添加global name(或完全消除全局变量)。

于 2013-11-01T17:04:59.533 回答
2

最简洁的答案是不。

有点扩展的答案:不,不是以便携式方式。从技术上讲,您可以使用 CPython 字节码,但是

  • 不会在任何其他解释器上运行,
  • 没有人能够理解该代码,
  • 头痛是不值得的。
于 2013-11-01T17:05:10.623 回答
0

定义一个包装类name

class Person(object):
    def __init__(self):
        self.name = "John"

    def set_name(self):
        self.name = "Sara"

    def print_name(self):
        print(name)

p = Person()
p.print_name()   # Prints John
p.set_name()     # Changes name to Sara
p.print_name()   # Prints Sara

像这样硬编码其属性值的类当然有点愚蠢,但这说明了类的目的:封装数据(name)和对其进行操作的函数(set_name, print_name)。

于 2013-11-01T17:58:05.783 回答
0
name = "John" #global name

和 set_name() 中的名称:

name = "Sara" #local name

要在函数内使用全局名称,set_name()请执行以下操作:

def set_name():
   global name
   name = "Sara"
于 2013-11-01T17:09:26.107 回答
0

不确定,为什么你要装饰二传手。

你可以做这样的事情,但我不推荐它作为通常的编码风格:

name = "John"

def print_name():
    print name

def decorator(func, tmp_name):
    def wrapper(*args, **kwargs):
        global name
        old_name = name
        name = tmp_name
        func(*args, **kwargs)
        name = old_name
    return wrapper

print_name()
decorator(print_name, 'Sarah')()
print_name()

输出:

John
Sarah
John
于 2013-11-01T18:19:29.103 回答