Pythonでの「グローバル」キーワードの使用


285

ドキュメントを読んで理解したのは、Pythonには関数用の個別の名前空間があり、その関数でグローバル変数を使用する場合はを使用する必要があるということglobalです。

私はPython 2.7を使用していますが、この小さなテストを試しました

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

なしでも問題なく動作しているようglobalです。問題なくグローバル変数にアクセスできました。

何か不足していますか?また、以下はPythonのドキュメントからの抜粋です。

グローバルステートメントにリストされた名前は、仮パラメーターとして、またはforループ制御ターゲット、クラス定義、関数定義、またはインポートステートメントで定義してはなりません。

仮パラメーターとクラス定義は私には意味がありますが、forループの制御ターゲットと関数定義の制限を理解できません。


1
私はあなたがグローバルキーワードの使用を必要とするPHPと混同していると思います
-Python

11
あなたの言葉遣いに注意してください:Pythonは(あなたが持っている可能性を意味するであろう機能のために別々の名前空間がないdef foo(): ...foo = ...同時に)を。すべての関数呼び出しに対して新しいスコープを作成します。(しかし、これは世界中の他のすべてのリモート高水準言語とどのように違うのですか?)

回答:


366

このキーワードglobalは、ローカルコンテキストでグローバル変数を変更または作成する場合にのみ役立ちますが、グローバル変数を作成することが適切な解決策と見なされることはめったにありません。

def bob():
    me = "locally defined"    # Defined only in local context
    print(me)

bob()
print(me)     # Asking for a global variable

上記はあなたに与えるでしょう:

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print(me)
NameError: name 'me' is not defined

globalステートメントを使用すると、変数は関数のスコープの「外」で使用できるようになり、事実上グローバル変数になります。

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print(me)

bob()
print(me)     # Asking for a global variable

したがって、上記のコードはあなたに与えるでしょう:

locally defined
locally defined

さらに、Pythonの性質によりglobal、ローカルコンテキストで関数、クラス、またはその他のオブジェクトを宣言するために使用することもできます。何かがうまくいかなかったり、デバッグが必要な場合に悪夢を引き起こすので、私はそれを勧めません。


59
この文脈での「グローバル」は、「グローバル」と見なされる他の言語とは異なるように見えます。Pythonでは、「グローバル」参照は依然としてモジュールの範囲内にあり、そのモジュールの外部から、期待される単純な「global_var」ではなく「module.global_var」として参照する必要があります。
ジュース

17
@juice-Pythonでは、globals(ありがたいことに)すべての名前空間にわたって絶対的に自動的に定義されるようなものはありません。正しく指摘したように、グローバルはモジュール内の名前空間にバインドされていますが、from module import variableまたはとして別のモジュールにインポートできますimport module.variable。最初のケースでは、インポートはとしてvariable参照を必要とせずに変数にアクセスできるようにしますmodule.。モジュールのスコープでグローバルと見なされるかどうかは、インポート先によって異なります。参照nonlocalのpython 3に新しいスコープの関連キーワードとして
unode

3
グローバル変数が良い解決策ではない理由を説明できますか?私はよくこれを聞きますが、私の現在のプロジェクトでは、彼らは私がする必要があることだけをしているようです。私が考えていないもっと不吉なものはありますか?
ロビンニューハウス2013年

5
@RobinNewhouse SOには、その トピックと他の非SO 記事をすでにカバーしいるいくつかの質問があります。
unode 2013年

213

globalキーワードがなくてもグローバル変数にアクセスできますが、変更する場合はglobalキーワードを使用する必要があります。例えば:

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo

あなたの場合、あなたはリストにアクセスしているだけですsub


3
注意点の1つfoo = 3は、グローバルな動作なしですが、fooはblub関数スコープでローカルに再定義され、元のfoo変数を変更しないことです。これは私をかなり混乱させました。
チャンティアル2018

1
@chhantyalが動作する場合、それはエラーをスローしないことを意味しますが、正しいですが、Ivo Wetzelのコンテキストでは、意図したとおりに機能しません。このような振る舞いにはいくつかの用途がありますが、プログラマーが望んでいないことはよくあります。
democidist

77

これが、名前へのアクセスとスコープ内でのバインドの違いです。

変数を調べてその値を読み取るだけの場合は、ローカルスコープだけでなくグローバルスコープにもアクセスできます。

ただし、名前がローカルスコープにない変数に割り当てると、その名前がこのスコープにバインドされます(その名前がグローバルとしても存在する場合は、非表示になります)。

グローバル名に割り当てられるようにするには、新しいローカル名をバインドするのではなく、グローバル名を使用するようにパーサーに指示する必要があります。これが「グローバル」キーワードの役割です。

ブロック内のどこかにバインドすると、そのブロック内のどこにでも名前がバインドされます。これにより、奇妙に見える結果が発生する可能性があります(たとえば、UnboundLocalErrorが以前に機能していたコードに突然表示されます)。

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 

非常に直感的ではなく、これが有効なpythonコードであるとは信じがたい
PlsWork

52

他の答えはあなたの質問に答えます。Pythonの名前について知っておくべきもう1つの重要なことは、スコープごとにローカルまたはグローバルであることです。

たとえば、次のことを考慮してください。

value = 42

def doit():
    print value
    value = 0

doit()
print value

value = 0ステートメントはローカル変数に割り当てられ、doit()関数の外部で宣言された同じ変数の値には影響しないと推測できます。上記のコードが実行されないことに気付くともっと驚くかもしれません。print value関数内のステートメントは、UnboundLocalError.

その理由は、Pythonは他の場所の関数で、あなたが名前を割り当てる、ということに気づいたことがありvalue、また、valueどこにも宣言されていませんglobal。それはそれをローカル変数にします。しかし、それを印刷しようとしたとき、ローカル名はまだ定義されていません。この場合のPythonは、他の一部の言語のように、名前をグローバル変数として探すことにフォールバックしません。基本的に、関数内のどこかに同じ名前のローカル変数を定義している場合は、グローバル変数にアクセスできません。


1
これを指摘してくれてありがとう。したがって、ローカルスコープがその外部に存在する名前に割り当てられない限り、ローカルスコープでの参照には外部名が使用されます。ただし、関数内のどこかにその名前を割り当てた場合、そのローカルスコープでの参照は、ローカル割り当ての前であっても、外部を見ないでください。
ドミトリーミンコフスキー2013

1
まさに、あなたはそれを手に入れました。global(またはnonlocalPython 3.xでは)この動作をオーバーライドし、外部名を再割り当てできるようにします。
キンダル2013

2
他の言語では、これは例えば次のように、「巻き上げ」と呼ぶことにするようだ:github.com/shichuan/javascript-patterns/blob/master/...
ドミトリーMinkovsky

傷害に侮辱を追加するには、変数は、キーワード、新しいJavaScriptで宣言letされていない掲揚します。
キンダル

で宣言されたグローバル変数にアクセスする方が速いglobalですか、それとも問題ありませんか?
マト

14

名前へのアクセスと名前の割り当ては異なります。あなたの場合、あなたは名前にアクセスしているだけです。

関数内の変数に割り当てる場合、グローバルに宣言しない限り、その変数はローカルであると見なされます。それがない場合は、グローバルであると見なされます。

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2

7
  • キーワードなしでグローバルキーワードにアクセスできます global
  • それらを変更できるようにするには、キーワードがグローバルであることを明示的に述べる必要があります。それ以外の場合、キーワードはローカルスコープで宣言されます。

例:

words = [...] 

def contains (word): 
    global words             # <- not really needed
    return (word in words) 

def add (word): 
    global words             # must specify that we're working with a global keyword
    if word not in words: 
        words += [word]

2

関数の外部で宣言された変数はすべてグローバルであると見なされます。変数をグローバルにするように指定する必要があるのは、関数(コンストラクタを除く)の内部から宣言する場合のみです。


1

これはPython FAQでよく説明されています

Pythonのローカル変数とグローバル変数のルールは何ですか?

Pythonでは、関数内でのみ参照される変数は暗黙的にグローバルです。変数に関数本体内のどこかに値が割り当てられている場合、明示的にグローバルとして宣言されていない限り、変数はローカルであると見なされます。

最初は少し意外ですが、少し考えてみればこれについて説明できます。一方で、global割り当てられた変数を要求することは、意図しない副作用に対する障壁を提供します。一方、globalすべてのグローバル参照に必要な場合は、常に使用しglobalます。global組み込み関数またはインポートされたモジュールのコンポーネントへのすべての参照として宣言する必要があります。この混乱は、global副作用を特定するための宣言の有用性を無効にします。

https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python


0

つまり、次のことは行わないでください。

x = 1

def myfunc():
  global x

  # formal parameter
  def localfunction(x):
    return x+1

  # import statement
  import os.path as x

  # for loop control target
  for x in range(10):
    print x

  # class definition
  class x(object):
    def __init__(self):
      pass

  #function definition
  def x():
    print "I'm bad"

- ikostiaは、グローバルに使用したために「X」を使用することはできませんすべてのもの列挙されdocs.python.org/reference/...
pycruft

1
@Unode:NikhilRathodが彼の引用で示したすべてのケースをデモしているだけです。
ikostia '14年

0

グローバルは変数を「グローバル」にします

def out():
    global x
    x = 1
    print(x)
    return


out()

print (x)

これにより、「x」は関数の外では通常の変数のように機能します。グローバルを削除すると、関数内で変数を出力できないため、エラーが発生します。

def out():
     # Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
    x = 1
    print(x)
    return


out()

print (x)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.