我有一个设置name
变量但在第一行没有global name
的方法,它使用本地name
变量,因此它永远不会更改全局name
1}}变量。
有没有办法通过装饰set_name
强制它使用全局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
答案 0 :(得分:2)
不,除非装饰器获取函数的代码(来自函数的代码对象的字节码,或使用inspect
的源代码),否则更改它,从更改的代码创建新的代码对象并用该代码替换函数的代码。当然,这是非常不可靠,黑客,具体实施和黑暗魔法。只需添加global name
(或完全删除全局变量)。
答案 1 :(得分:2)
简短的回答是:不。
有点扩展答案:不,不是以便携方式。从技术上讲,你可以使用CPython字节码,但是
答案 2 :(得分:0)
name = "John" #global name
和set_name()中的名称:
name = "Sara" #local name
要在函数set_name()
中使用全局名称,请执行以下操作:
def set_name():
global name
name = "Sara"
答案 3 :(得分: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
)和函数({{1} ,set_name
)对其进行操作。
答案 4 :(得分:0)
不确定,为什么要尝试装饰setter。
你可以这样做,但我不推荐它作为一种通常的编码方式:
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