Doug と Jim からの回答を読んだ後、これがどのように機能するかについてのアイデアがあると思います。まず第一に、例は REPL (Ipython、デフォルト) で動作します
ファイル: これをファイルに書き込む場合:
if True:
print("Hi")
else:
I am an error. What can you do about it?
ファイルを実行すると、SyntaxError がスローされます。これは、ファイルから Python コードを実行するたびにバイトコードが生成され、else のステートメントが有効な Python 式ではないため、SyntaxError が発生することを証明しています。
REPL : REPL を使用すると、少し依存関係が生じます。次のように入力すると、Pythonインタープリターで
>>>def foo():
if True:
print("Hey")
else:
I am an error. What can you do about it?
>>>foo()
Hey
実行が成功すると、バイトコードはありませんよね?持続する。
これを書くと:
>>>x = 10
>>>def foo():
print(x)
x += 1
>>>foo()
そしてブーム!すべてがバラバラになり、 print(x) ステートメントで UnboundLocalError が発生します。つまり、バイトコードが存在します。
では、ここで何が起こっているのでしょうか。
Python は、変数の 1 つの出現を見つけると、最初にそれらすべてを読み取ることによって、その動作を最適化しようとします。したがって、コードが print(x) に遭遇した 2 番目の例では、x のすべての操作を検索しようとします。すぐにステートメント x+=1 が見つかります。ローカル スコープには x の言及がなく、明示的に言及されていない場合、python はグローバル スコープで変数を検索しないため、次のようになります。
UnboundLocalError: local variable 'x' is referenced before assignment
決定的な証拠
次のように書くと:
>>>x = 10
>>>def foo():
if True:
print(x)
else:
x+=1
>>>foo()
UnboundLocalError: local variable 'x' referenced before assignment
それでおしまい!
x+=1 は実行されませんでしたが、print ステートメントが x を出力し、別の参照 (x+=1) が問題だったため、値を出力する前にエラーが発生しました。最初のケースは、REPL の SyntaxError がなくても問題なく動作しました。これは、else ステートメント内を調べる必要がなかったためです。