4

[再現可能な例を示すためのコミュニティ編集:]

def main():
    e = None
    print(locals())
    while not e:
        try:
            raise Exception
        except Exception as e:
            pass            

main()

を生成します

~/coding$ python3.3 quiz2.py
{'e': None}
Traceback (most recent call last):
  File "quiz2.py", line 11, in <module>
    main()
  File "quiz2.py", line 5, in main
    while not e:
UnboundLocalError: local variable 'e' referenced before assignment

[編集済み]再現可能なコードを含める

whileループを実行しようとしていますが、使用する条件は、変数がe==None。関連するコードは次のとおりです。

    print("\nThe current score list contains the following people's scores: ")
    score_list = open("score_list.dat", "rb")
    score_name = []
    e = None
    while not e:
        try:
            score = pickle.load(score_list)
            name = pickle.load(score_list)
            score_name.append([score, name])
        except EOFError as e:
            pass            
    score_list_sorted=sorted(score_list)
    sort_list.close()
    for item in score_list_sorted:
        print("Score: ", item[0], "\t", item[1])

完全なコードはここにあります:https://www.dropbox.com/s/llj5xwexzfsoppv/stats_quiz_feb24_2013.py

(クイズを実行するために)必要なデータファイルは、次のリンクにあります。https://www.dropbox.com/s/70pbcb80kss2k9e/stats_quiz.dat

main()適切なデータファイルアドレスを使用するには、次のように編集する必要があります。

私が受け取った完全なエラーメッセージは以下のとおりです。ewhileループの直前に初期化したので、これは奇妙です。誰かが私がこの問題を解決するのを手伝ってくれることを願っています。ありがとう!

Traceback (most recent call last):
  File "<pyshell#217>", line 1, in <module>
    main()
  File "/Users/Dropbox/folder/stats_quiz_feb24_2013.py", line 83, in main
    while not e:
UnboundLocalError: local variable 'e' referenced before assignment
4

2 に答える 2

10

このエラーはtry...except...、Python 3 の機能である新しいスコープが原因で発生します。PEP-3110
を参照

Python 3 では、次のブロック

try:
    try_body
except E as N:
    except_body
...

に翻訳されます (Python 2.5 用語で)

try:
    try_body
except E, N:
    try:
        except_body
    finally:
        N = None
        del N
...

したがって、Python 3 のこの関数は

def main():
    e = None
    print(locals())
    while not e:
        try:
            raise Exception
        except Exception as e:
            pass

と同等です

def main():
    e = None
    print(locals())
    if not e:
        try:
            raise Exception
        except Exception as e:
            pass
        del e
    if not e:
        try:
            raise Exception
        except Exception as e:
            pass
        del e
    ...

etry except初期化されましたが、最初のブロックの後に削除されています。
したがって、UnboundLocalError必然です。

于 2013-02-25T23:08:39.517 に答える
5

まあ、実際の問題の原因はわかりませんがbreak、例外が発生したときにだけ使用しないのはなぜですか? ループは次のようになります。

while True:
    try:
        score = pickle.load(score_list)
        name = pickle.load(score_list)
        score_name.append([score, name])
    except EOFError as e:
        break

私の知る限り、これは「例外がない間にループを実行する」ための慣用的な方法です。

編集:なぜこれが起こるのか

Python3 では、例外ハンドラーのスコープを終了すると、例外がバインドされていた変数が名前空間から削除されるようです。コードを次のように変更しました。

def main():
    e = None
    print(locals())
    while not e:
        try:
            raise Exception
        except Exception as e:
            pass
        print(locals())

main()

出力:

{'e': None}
{}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in main
UnboundLocalError: local variable 'e' referenced before assignment

これは、python2 には当てはまりません。例外を変数に割り当てる方法の構文が変更されたことを考えると、そのセマンティクスも変更されたことに驚きはありません。これは「驚くべき」動作だと思いますが(期待するものではないという意味で)。

いずれにせよ、例外が発生したときにループを終了する適切な方法は、上記のコードにあります。例外を例外ハンドラーのスコープ外に保持したい場合は、次のようなことができると思います。

def main():
   e = None
   print(locals())
   while not e:
      try:
         raise Exception
      except Exception as ex:
         e = ex
      print(locals())

main()

次の出力が生成されます。

{'e': None}
{'e': Exception()}

ただし、特定のユースケースでは実際にそれを行うべきではありません。

于 2013-02-25T22:49:51.283 に答える