Python Jython全局变量用法

时间:2012-09-11 16:34:03

标签: python scope jython global

我对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'}

除了更简单之外,现在工作得非常好。

3 个答案:

答案 0 :(得分:2)

global都没有按照您的想法行事。在这两种情况下,chosenchosen2都是 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。在您的示例中,chosenchosen2是类属性。而不是:

global chosen
chosen = self.choice

你只需写:

self.chosen = self.choice

在课前定义chosen2时,实际上是在global引用的范围内定义它。当您在类范围内定义时,它是所有实例共享的类属性。

正如所指出的那样

更新:,对class属性的直接赋值不是你想要的,因为它会在实例上创建一个新的属性,在类上掩盖它。但是在你的Listener2示例中,这没关系:

def actionPerformed(self, event):
    self.chosen[self.choice] = event

在这里,你不是要覆盖.chosen,而是将一个项目添加到它引用的字典中,这样该类将为每个监听器记录最近的事件。