2

重複の可能性:
Python 変数スコープの質問

Python マニュアルでは、スコープを次のように定義しています。

スコープは、ブロック内の名前の可視性を定義します。ローカル変数がブロックで定義されている場合、そのスコープにはそのブロックが含まれます。定義が関数ブロックで発生する場合、含まれるブロックが名前の別のバインディングを導入しない限り、スコープは定義ブロック内に含まれるすべてのブロックに拡張されます。

私はこのプログラムを持っています:

import random
def f():
  a = "Is the scope static?"
  if random.randint(0, 1) == 1:
    del a
  print a

印刷が失敗する確率は 50% です。

>>> f()
Is the scope static?
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in f
UnboundLocalError: local variable 'a' referenced before assignment

それによって、print ステートメントが 'a' の範囲外である可能性は 50% あると思いますが、私は間違っている可能性があります。Pythonでのスコープの「正しい」解釈は何ですか? Pythonの変数のスコープは静的に定義されていますか? 変数「a」のスコープは?

4

3 に答える 3

11

名前のスコープはa関数全体であり、f純粋に静的です。「print ステートメントが範囲外である可能性が 50% ある」というのはまったく正しくありませんa。名前検索が失敗する理由は、「範囲外」だけではありません。

この関数から得られるエラーに注意してください。

>>> def foo():
...   print a
... 
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in foo
NameError: global name 'a' is not defined

関数が実行されたときに発生するエラーとは異なりますdel a。私のfooではa、 のローカル スコープで定義されていなかったfooため、名前の検索はグローバル スコープに進みましたが、aどちらも見つからなかったため、グローバル が存在しないという例外が発生しましたa

a表示されるエラーは、名前が のローカル変数であることを Python が認識していることを明確に示していますf。ただし、削除したため、価値はありません。(通常、これは、ローカル変数に書き込みを行う前にローカル変数を読み取ろうとした場合にのみ発生します。そのため、エラー メッセージはそのように表現されています)

この場合にも注意してください。

a = 3
>>> def bar():
...   a = 1
...   del a
...   print a
... 
>>> bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in bar
UnboundLocalError: local variable 'a' referenced before assignment

Python は、ローカルに値がないことを訴えaます。a単純にローカル スコープにない場合は、aグローバルに検索して次を見つけます3

>>> a = 8
>>> def baz():
...   print a
... 
>>> baz()
8

delこれは、グローバル スコープから取得した場合とは異なる動作です。

>>> a = 12
>>> del a
>>> print a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

aここでは、存在しなかったかのように例外が発生します。この違いの理由は関数のローカル スコープがstaticであるためです。関数に名前への割り当てが含まれている場合、その名前は関数の本体全体にローカルに適用されます1。最初の代入の前、またはそれdelを取り除くために使用した後であっても、その関数でその名前を検索すると、ローカル変数の値を取得しようとします。


1名前が宣言されていない場合、globalまたはnonlocal.

于 2012-10-15T23:00:20.027 に答える
3

Python は次LEGBのルールに従います。

L: Local          # Current def
E: Enclosing      # Any enclosing def
G: Global         # Globals
B: Built-in       # Built-ins

あなたの質問はLです。

于 2012-10-15T22:17:20.033 に答える
1

クラス、関数、およびモジュールのみが Python でスコープを提供しifwhile他のループ/分岐構造はスコープを提供しません。

ドキュメントから:

スコープは静的に決定されますが、動的に使用されます。実行中はいつでも、名前空間に直接アクセスできるネストされたスコープが少なくとも 3 つあります。

the innermost scope, which is searched first, contains the local names
the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
the next-to-last scope contains the current module’s global names
the outermost scope (searched last) is the namespace containing built-in names

コードaでは、ローカル名前空間で定義し、それも削除します。ブランチで使用delするifことは、関数の他の場所で使用することとまったく同じです。

于 2012-10-15T22:18:44.667 に答える