web-dev-qa-db-ja.com

pythonのグローバル変数警告

次のようなpython 2.6スクリプト(少なくとも2.7にアップグレードする必要があることは知っています))があります。

ret_code = 0

def some_func()
  global ret_code
  ...

if __== '__main__':
  global ret_code
  ...

コードを実行すると、警告が表示されます。* SyntaxWarning:name 'ret_code'は、グローバル宣言global ret_code *の前に割り当てられます*

この警告が表示されるのはなぜですか?

そうすることで問題を解決できます:

def some_func()
      global ret_code
      ...

if __== '__main__':
  global ret_code
  ret_code = 0 #assign 0 here instead of above
  ...

それでもそれは私の質問に答えません。元のコードの何が問題になっていますか?

43
whomaniac

これを修正する最良の直接的な方法は、_if __== '__main__':_の下からglobal宣言を削除することです。必要ありません。他の言語とは異なり、ifステートメントはPython-そのブロックで割り当てる変数はグローバルであり、そこにifがない場合と同様に、新しいスコープを導入しません。

これはエラーである理由も説明します:変数をglobalとして宣言するために、以前に同じスコープでその変数名を使用することは許可されていません(おそらくglobalステートメントが割り当てを行うのを混乱させるためですbeforeグローバル変数に移動し、Pythonは同じスコープ内でグローバルとローカルの両方である同じ名前をサポートしません)。ifは新しいスコープを導入しないため、 _ret_code_への最初の割り当ては、ifの下のグローバル宣言と同じスコープ内にありますが、グローバル宣言は割り当てよりも後になりますが、これは許可されていません。

さらに改善するには、プログラムから変更可能なグローバル状態を完全に削除できるかどうかを検討します。これは、通常、どこかに価値があるよりも多くの問題を引き起こすためです。ここでは、プログラム終了コードとして_ret_code_を使用している可能性が高いようです-つまり、どこかでsys.exit(ret_code)を実行していますが、使用する終了コードを関数内で決定しています。代わりに、使用する終了コードを決定するためにitのトップレベルコードに十分な情報を返します。

91
lvc