我对python全局变量及其正确用法的理解存在问题。第一位代码工作正常,第二位抛出异常“NameError:全局名称'选择'未定义”。我相信我在这里缺少一些简单的东西,但我看不出它是什么。
我想将一个Listener与许多事件生成器中的每一个相关联,然后使用getChoices方法获取每个生成器所做选择的字典。
#Working code
class Listener1():
chosen = "0"
def __init__(self, choice):
self.choice = choice
def actionPerformed(self, event):
global chosen
chosen = self.choice
@staticmethod
def getChoices():
return chosen
e1 = Listener1('evt1')
e1.actionPerformed('abc')
print Listener1.getChoices()
代码失败
class Listener2():
chosen2 = {'a':-1}
def __init__(self, choice):
self.choice = choice
global chosen2
chosen2[self.choice] = 'unset'
def actionPerformed(self, event):
val = event
global chosen2
chosen2[self.choice] = val
@staticmethod
def getChoices():
return chosen2
e2 = Listener2('evt2')
e2.actionPerformed('def')
e3 = Listener2('evt3')
e3.actionPerformed('ghi')
print Listener2.getChoices()
脚注: 如果我将第一个引用全局变量 selected2 移动到类定义之前的行而不是之后的行,则Listener2类可以正常工作。
感谢下面的答案,代码重写为:
class Listener3():
chosen3 = {}
def __init__(self, choice):
self.choice = choice
if choice is not None:
self.chosen3[self.choice] = 'unset'
def actionPerformed(self, event):
val = event
self.chosen3[self.choice] = val
def getChoices(self):
return self.chosen3
e1 = Listener3('evt1')
e1.actionPerformed('abc')
e2 = Listener3('evt2')
e2.actionPerformed('def')
e3 = Listener3('evt3')
print Listener3(None).getChoices()
{'evt1': 'abc', 'evt2': 'def', 'evt3':'unset'}
除了更简单之外,现在工作得非常好。
答案 0 :(得分:2)
global
都没有按照您的想法行事。在这两种情况下,chosen
和chosen2
都是 class 变量,而不是全局变量。
但是当你将chosen
声明为全局并分配给它时,python愉快创建一个全局变量(与Listener1.chosen
分开)并存储你的值。
但对于chosen2
,你没有给它任何东西;您试图将其视为dict,但您没有通过赋值创建变量,因此失败。
您想要使用self.chosen2
;作为一个类变量,它将可用于Listener2
的所有实例。您也可以使用Listener2.chosen2
。对于chosen
,您可以使用Listener1.chosen
来引用它。 global
个关键字可以完全删除。
在任何情况下,将变量声明为global
并不意味着在我当前范围之外。它意味着在模块范围,因此总是在函数,类和方法定义之外。
答案 1 :(得分:0)
您可以重新创建相同的错误:
global chosen2 #you're not creating chosen2, just saying you're about to create it, and when you do - it should be a global variable
chosen2[2]=2 #chosen2 has yet to be defined so how can you set anything?
您正在尝试设置尚未定义的对象two
的属性,首先您必须说明您是希望它是列表还是字典(或其他)。
global chosen2
chosen2={}
chosen2[2]=2
如上所述,我认为您不希望这是全局的(因为您希望能够使用selected2的不同值创建类实例!
答案 2 :(得分:0)
您无需在此处使用global
。在您的示例中,chosen
和chosen2
是类属性。而不是:
global chosen
chosen = self.choice
你只需写:
self.chosen = self.choice
在课前定义chosen2
时,实际上是在global
引用的范围内定义它。当您在类范围内定义时,它是所有实例共享的类属性。
更新:,对class属性的直接赋值不是你想要的,因为它会在实例上创建一个新的属性,在类上掩盖它。但是在你的Listener2
示例中,这没关系:
def actionPerformed(self, event):
self.chosen[self.choice] = event
在这里,你不是要覆盖.chosen
,而是将一个项目添加到它引用的字典中,这样该类将为每个监听器记录最近的事件。