1

Pythonグローバル変数とその正しい使用法の理解に問題があります。コードの最初のビットは正常に機能し、2番目のビットは「NameError:グローバル名'選択された'が定義されていません」という例外をスローします。ここでは単純なものが欠けていると思いますが、それが何であるかはわかりません。

リスナーを多くのイベントジェネレーターのそれぞれに関連付けてから、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()

脚注:グローバル変数chosen2への最初の参照をクラス定義の後の行ではなく前の行に移動すると、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'}

そして、はるかに単純であることは別として、今では完璧に機能しています。

4

3 に答える 3

2

globalあなたが思っていることもしません。どちらの場合もchosen、とchosen2クラス変数であり、グローバルではありません。

しかしchosen、グローバルとして宣言してそれに割り当てると、Pythonは喜んでグローバル変数(とは別)を作成Listener1.chosenし、値を格納しました。

しかし、chosen2あなたはそれに何も割り当てていません。代わりにそれをdictとして処理しようとしていますが、代入によって変数を作成しなかったため、失敗します。

self.chosen2代わりに使用します。クラス変数として、のすべてのインスタンスで使用できますListener2。を使用することもできますListener2.chosen2。については、それを参照するためにchosen使用できます。キーワードは完全に削除できますListener1.chosenglobal

いずれにせよ、変数を宣言することは、私の現在のスコープの外をglobal意味するものではありません。代わりにモジュールスコープを意味するため、常に関数、クラス、およびメソッド定義の外部にあります。

于 2012-09-11T16:39:11.003 に答える
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

前述のように、これをグローバルにしたくないと思います(chosen2の値が異なるクラスインスタンスを作成できるようにしたいためです!

于 2012-09-11T16:38:50.247 に答える
0

ここで使用する必要はありませんglobal。あなたの例では、chosenchosen2はクラス属性です。それ以外の:

global chosen
chosen = self.choice

あなたはただ書くでしょう:

self.chosen = self.choice

クラスの前に定義するときchosen2は、実際にはをglobal参照するスコープで定義しています。クラススコープ内で定義すると、すべてのインスタンスで共有されるクラス属性になります。

更新:指摘されているように、クラス属性への直接の割り当ては、クラス上でそれをマスクするインスタンス上に新しい属性を作成するため、あなたが望むものではありません。しかし、あなたのListener2例では、これで問題ありません。

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

ここでは、を上書きしていません.chosenが、参照するディクショナリにアイテムを追加しているため、クラスは各リスナーの最新のイベントの記録を保持します。

于 2012-09-11T16:39:48.297 に答える