関数内でグローバル変数を更新できない(globalキーワード忘れ)
関数の中で変数に代入すると、その変数は既定でローカル変数になります。外側の変数を更新したいときはglobal宣言が必要です。
なぜエラーが出ないのか
出力: 0
(エラーなし)- Pythonは何も報告しません。文法として正しいためです
出力: 0- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 count = 0 2 3 def set_count(n): 4 ^ 5 count = n 6 7 set_count(5) 8 print(count)
global宣言が無いと、count = n は関数内だけの新しいローカル変数を作るだけです。外側のcountは変わらないまま残ります。
直し方: (空) を global count にします。
パターン2
1 balance = 100 2 3 def deposit(amount): 4 ^ 5 balance = amount 6 7 deposit(500) 8 print(balance)
関数内のbalanceはグローバルとは別の変数として扱われます。呼び出し後も外側の値は変わりません。
直し方: (空) を global balance にします。
パターン3
1 status = "idle" 2 3 def start(): 4 ^ 5 status = "running" 6 7 start() 8 print(status)
文字列の状態管理でも同じです。関数内での代入は既定でローカル変数を作るだけなので、global宣言をしない限り外の変数には反映されません。
直し方: (空) を global status にします。
パターン4
1 inventory = 50 2 3 def restock(n): 4 ^ 5 inventory = n 6 7 restock(80) 8 print(inventory)
在庫を入れ替える関数でも同じです。global宣言が無いと関数の中だけで完結し、外の在庫数は変わりません。
直し方: (空) を global inventory にします。
パターン5
1 temperature = 20 2 3 def reset_temp(n): 4 ^ 5 temperature = n 6 7 reset_temp(0) 8 print(temperature)
値を置き換えるだけの単純な関数でも、global宣言を忘れると外側の変数には反映されません。
直し方: (空) を global temperature にします。
よくある誤解
エラーは一切出ません。関数は正常に実行され、意図した処理をしたように見えますが、外側の変数は変わらないままという、気づきにくい種類のバグです。
実務での勘所
読み取りには宣言が要らないのに書き込みだけglobal宣言が必要という非対称は、Pythonの「暗黙より明示を」という設計思想(The Zen of Pythonの一節)によるものです。もし宣言なしで書き込みも許してしまうと、うっかり同名のローカル変数のつもりで書いたコードがグローバル変数を意図せず書き換えてしまう事故が起きやすくなります。なお、関数の中の関数(クロージャ)から1つ外側の関数のローカル変数を書き換えたい場合は、globalではなくnonlocalという別のキーワードを使います。