不,问题不重复。这不是关于“如何在python中说a=1
”?
并非琐碎。请仔细阅读。
答案是:这是不可能的来创建这样的单线程,至少不使用脏黑客。请参阅接受的答案了解详情。
如果你不想读书,但为了方便业力来到这里,请经过并停止迷惑我,因为接受的答案非常有用。 :)
问题:
我正在做一些GUI编程,并希望创建一个非常短的信号处理程序,它将局部变量设置为一个值,以响应来自GUI的信号。
def function():
output = False #this is local variable; I want to change its value by signal handler
button = PyQt4.QtGui.QPushButton("simple button")
#next line sets output to True
button.pressed.connect(lambda:SOME_FUNCTION_I_AM_LOOKING_FOR(output, True))
#Now output==True
你能否建议用SOME_FUNCTION_I_AM_LOOKING_FOR
代替什么?显然,你不能只说button.pressed.connect(output=True)
,因为output=True
不是函数。
为了说明我在寻找的东西,这里是一个模拟:如果你想设置一个对象的属性,你可以使用setattr
函数。这是上面代码的模拟,设置属性而不是局部变量:
def function():
...
#create a dummy UserObject class and make an instance of it to store attributes
output_object = type('UserObject', (), {})()
output_object.it_was_pressed = False #flags that button was pressed
#when "pressed" signal of button is emitted, "it_was_pressed" attribute of output_object is set to True
button = PyQt4.QtGui.QPushButton("simple button")
button.pressed.connect(lambda: setattr(output_object, "it_was_pressed", True)
那是不我想做什么。我想要做的是创建一个类似物来设置一个局部变量来响应信号:
更新
我要求单线解决方案:简洁优雅。当然,我可以用3行做到这一点,但我不想这样做。
答案 0 :(得分:2)
没有 可靠的方式“以编程方式”修改本地环境(即没有明确的分配)。
例如,这适用于python2:
>>> def test():
... output = False
... exec('output=True')
... print(output)
...
>>> test()
True
>>> test()
True
然而, 在python3中无法正常工作!
>>> def test():
... output = False
... exec('output=True')
... print(output)
...
>>> test()
False
修改locals()
返回的字典可能不起作用,例如:
>>> def test(): #python 2 and 3
... output = False
... locals()['output'] = True
... print(output)
...
>>> test()
False
它可能适用于某些旧版本的python。
exec
可能在python2中有效,因为它是一个语句,因此python编译器可以确定该函数是否需要真正使用dict
来存储其变量并使exec
工作properly`。检查这个很简单:
>>> def test():
... exec('pass')
... locals()['output'] = True
... print(output)
...
>>> test()
True
>>> def test():
... locals()['output'] = True
... print(output)
...
>>> test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in test
NameError: global name 'output' is not defined
正如您可以看到函数是否包含exec
语句python避免优化局部变量而只使用dict
(从而使locals()
的更改正常工作)。如果未找到exec
,则更改无效。
在python3中exec
是一个函数,python编译器总是优化本地查找。
所以:
exec
做到这一点,但这是一个声明,不能在lambda
s 因此,您要求的是AFAIK,在一行的单个表达式中是不可能的(至少以任何合理的可读方式)。 正确做你想做的事的方法是在python3中使用nonlocal
:
output = False
def handler():
nonlocal output
output = True
button.pressed.connect(handler)
在python2中,你甚至没有nonlocal
所以你必须使用其中一个黑客来处理这个问题(比如输入output
一个元素列表等。)。
我不排除存在丑陋,不可读和 hackish 编写定义函数的单行的方式(不是lambda
!)而且可以达到你想要的效果,但我非常确定没有“简洁优雅”的单行程可以满足您的需求。
显然,如果你不介意output
成为一个清单,你可以做丑陋的事情:
output = [False]
button.pressed.connect(lambda: output.__setitem__(0, True))
答案 1 :(得分:0)
如果你只关心布尔检查,你可以依赖一些Pythonic习语:
output = {} # similar to False case
def callback_func(output, val):
if val:
output['set']=True
else:
output.clear()
如果字典为空,则将其评估为False,否则为true。