3

重複の可能性:
Pythonでの割り当てエラーの前に参照されています

Pythonで奇妙なエラーが発生します。次のipythonログはそれを要約しています:

In [10]: def confused(stuff):
   ....:     print huh
   ....:     return stuff
   ....: 

In [11]: confused(87)
0
Out[11]: 87

In [12]: def confused(stuff):
   ....:     print huh
   ....:     huh += 1
   ....:     return stuff
   ....: 

In [13]: confused(9)
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
/home/max/verk/btr-email/build/x86_64/bin/ipython in <module>()
----> 1 confused(9)

/home/max/verk/btr-email/build/x86_64/bin/ipython in confused(stuff)
      1 def confused(stuff):
----> 2     print huh
      3     huh += 1
      4     return stuff

UnboundLocalError: local variable 'huh' referenced before assignment

動作する関数とエラーをスローする関数の唯一の違いは+=1行であり、それでも、以前は動作していた行にエラーをスローします。また、メソッドの2番目のバージョンでglobal huh参照する前に配置しても、エラーはスローされません。huh

変数に1行追加すると、突然グローバル変数からローカル変数に変更されるのはなぜですか?

4

1 に答える 1

7

スクリプトでhuhは、グローバル変数を参照します。関数内のグローバル変数への参照を、それが何をしたいのかを明示的に Python に伝えずに変更することはできません。

def confused(stuff):
    global huh
    print huh
    huh += 1
    return stuff

int、string、float などの不変オブジェクトの場合、オブジェクトを .xml として宣言しないと変更できないことを意味しますglobal可変オブジェクトの場合、オブジェクトの項目または属性を変更できますが、オブジェクトの参照を変更することはできません。


これはすべて範囲の問題です。huhは のローカル スコープにないため、confusedpython はグローバル スコープでそれを見つけます。これはグローバル スコープにあるため、(上記で行ったように)特に指定しない限り、割り当てることはできません。globalただし、 の場合list、リストが見つかったら、そのリストのすべてのメソッド ( 、 などを含む) にアクセスでき__setitem__ますappend


disエラーの場所に関しては、少し組み立てることで解決できます。

>>> def confused(stuff):
...    print huh
... 

>>> import dis
>>> dis.dis(confused)
  2           0 LOAD_GLOBAL              0 (huh)
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE

>>> def confused2(stuff):
...    print huh
...    huh += 1
... 

>>> dis.dis(confused2)
  2           0 LOAD_FAST                1 (huh)
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       

  3           5 LOAD_FAST                1 (huh)
              8 LOAD_CONST               1 (1)
             11 INPLACE_ADD         
             12 STORE_FAST               1 (huh)
             15 LOAD_CONST               0 (None)
             18 RETURN_VALUE   

confused2では、関数の最初の行でpython が既にLOAD_FAST(つまり、ローカル変数を探す) ことを試みていることがわかります。ただし、ローカル変数huhが存在しないため、例外が発生します。

于 2013-01-07T18:07:49.387 に答える