2011-01-07 20 views
10

私のプログラムでいくつかの関数が動作するリストを使用しています。これは実際に共有リストであり、私のすべての関数はそれを編集できます。それをすべての関数で「グローバル」として定義することは本当に必要ですか?Pythonでグローバル変数としてリストを定義する

グローバルキーワードを使用する各関数にそのキーワードを置くか、すべての関数の外で定義することは、その定義の後ろにあるグローバル単語を使用しないと十分ですか?

+5

あなたはグローバル変数がeeeevilあることを知っていますか?可能な場合は、引数以外のものに依存する関数を記述しないでください。非常にまれな状況でない限り、複数の点からグローバルなものを変更しないでください。それはほとんど必要ではなく、後で大きな頭痛を加える傾向があります。結論として、その価値はありません。 – delnan

答えて

22

もし変数(x = ...)を割り当てるときは、(現在の機能に例えばローカル)現在のスコープ内の変数を作成しています。変数fronを外側(例えばグローバルスコープ)でシャドーすると、あまりにも悪い - Pythonは気にしません(それは良いことです)。だからあなたはこれをすることができません:

x = 0 
def f(): 
    x = 1 
f() 
print x #=>0 

と期待1

x = 0 
def f(): 
    global x 
    x = 1 
f() 
print x #=>1 

しかし、変数の割り当てはメソッド呼び出しとは非常に異なっている点に注意してください。その代わり、あなたがglobal xを使用することを宣言します必要があります。スコープ内のすべてのメソッドをいつでも呼び出すことができます。外側(例えば、グローバル)スコープから来る変数には、局所的に影を付けるものはないからです。

は非常に重要な:メンバーの割り当て(x.name = ...)、項目の割り当て(collection[key] = ...)、スライス割り当て(sliceable[start:end] = ...)とpropably以上であるすべての方法は、同様に呼び出されます!したがって、グローバルのメンバを変更したり、メソッドを呼び出す場合(オブジェクトを変更した場合でも)、globalは必要ありません。

+4

+1。スライスの割り当てが参照を上書きしないことにも注意してください。特に、 'x = newlist'の代わりに、' x [:] = new_list'を実行でき、 'global'を使う必要はありません。もちろんこれはメソッド呼び出しのケースの対象ですが、明示的に指摘する価値があります。 – aaronasterling

+0

@aaron:はい。実際にはメソッド呼び出しは、メンバーの割り当て、スライスの割り当てなど、さまざまなことがあることを明確にするために拡張されました。 – delnan

4

はい、書き込む場合はglobal fooを使用する必要があります。

foo = [] 

def bar(): 
    global foo 
    ... 
    foo = [1] 
+1

厳密に間違ってはいませんが(例では、 'global'が必要です)、これは誤解を招きます。初心者にとっては、多くの人がPythonの "書き込み"の概念に同意していないようです。 – delnan

+0

ありがとう、これは辞書の場合にも当てはまりますか? – Hossein

+2

@Hossein:どの変数でも同じです。参照されるオブジェクトは関係ありません。 – delnan

1

いいえ、関数のキーワード引数としてリストを指定できます。

alist = [] 
def fn(alist=alist): 
    alist.append(1) 
fn() 
print alist # [1] 

私はそれが悪い習慣だと思います。一種のハッキリ。グローバルに利用可能なシングルトンのようなデータ構造を実際に使用する必要がある場合は、モジュールレベルの変数アプローチを使用します。すなわち、 'alist'をモジュールに入れ、次に他のモジュールでその変数をインポートします。

ファイルfoomodule.py:ファイルbarmodule.pyで

alist = [] 

:もちろん

import foomodule 
def fn(): 
    foomodule.alist.append(1) 
print foomodule.alist # [1] 
+0

説明:「グローバル」は常に*モジュールレベルです。特別なモジュールに入れる必要はありません。 – delnan

+0

私は関与する複雑さを知らなかった。私が書いた2つの例は、モジュールレベルの変数を変更する(つまり、グローバル名に代入しない)ことだけが必要な場合は、まったく必要ないと思われます。はるかに良い評価のためのデルナンの答えを参照してください。 – XORcist

関連する問題