8

コード1

x = 0

class Foo:
    print(x)
    x = 1
    print(x)

print(x)

結果1

0
1
0

コード2

x = 0

def foo():
    print(x)
    x = 1
    print(x)

foo()

結果2

UnboundLocalError: local variable 'x' referenced before assignment.

xの2つの名前空間からオブジェクトを参照できるのはなぜclass blockですか?なぜ投げないの
かわかりません。 関数とクラスの不一致が気になります。Code 1UnboundLocalError


アップデート:

Python Docsを数回読んだ後でも、スコープのルールを理解できません。

ブロックは次のとおりです。モジュール、関数本体、およびクラス定義。...[スキップ]...

名前がブロックにバインドされている場合、非ローカルとして宣言されていない限り、その名前はそのブロックのローカル変数です。名前がモジュールレベルでバインドされている場合、それはグローバル変数です。(モジュールコードブ​​ロックの変数はローカルおよびグローバルです。)変数がコードブロックで使用されているが、そこで定義されていない場合、それは自由変数です。

名前バインディング操作がコードブロック内のどこかで発生した場合、ブロック内での名前の使用はすべて、現在のブロックへの参照として扱われます。これにより、名前がバインドされる前にブロック内で使用された場合にエラーが発生する可能性があります。このルールは微妙です。Pythonには宣言がなく、名前バインディング操作をコードブロック内のどこでも実行できます。コードブロックのローカル変数は、ブロックのテキスト全体をスキャンして名前バインディング操作を行うことで判別できます。

4

3 に答える 3

6
x = 0

class Foo:
    print(x)   # Foo.x isn't defined yet, so this is the global x
    x = 1      # This is referring to Foo.x
    print(x)   # So is this

print(x)

x = 0

def foo():
    print(x)   # Even though x is not defined yet, it's known to be local
               # because of the assignment
    x = 1      # This assignment means x is local for the whole function
    print(x)

foo()
于 2012-10-10T00:49:53.027 に答える
1

global例を比較できるようにするには、次のステートメントを使用することを忘れないでください。

def foo():
    global x
    print(x)
    x = 1
    print(x)

この方法では、UnboundLocalError.

于 2012-10-10T00:52:28.100 に答える
1

クラスブロックは「ローカル」変数を認識せず、クラス変数のみを認識します。ブロックの実行後に忘れられないという点で、ローカル変数とは異なります。それらはクラスのフィールドとして残ります。ローカル変数とクラス変数は、この側面以外でも異なる方法で処理されるため、バインドされていないエラーが発生しないことはそれほど驚くべきことではありません。結局のところ、グローバル変数をシャドウする未定義のローカル変数はありません。そのため、クラス変数を定義する前にグローバル変数にアクセスしても問題ありません。

おそらく、コンパイラはこれについて何らかの形で警告する必要がありますが、現在は警告していません。

于 2012-10-10T00:52:56.080 に答える