Code Fix

中級

関数内でグローバル変数を更新できない(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)
出力: 0期待: 5 (エラーにはなりません)

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)
出力: 100期待: 500 (エラーにはなりません)

関数内のbalanceはグローバルとは別の変数として扱われます。呼び出し後も外側の値は変わりません。

直し方: (空) を global balance にします。

この問題を解いてみる →

パターン3

 1  status = "idle"
 2  
 3  def start():
 4                        
                 ^
 5      status = "running"
 6  
 7  start()
 8  print(status)
出力: idle期待: running (エラーにはなりません)

文字列の状態管理でも同じです。関数内での代入は既定でローカル変数を作るだけなので、global宣言をしない限り外の変数には反映されません。

直し方: (空) を global status にします。

この問題を解いてみる →

パターン4

 1  inventory = 50
 2  
 3  def restock(n):
 4                        
                 ^
 5      inventory = n
 6  
 7  restock(80)
 8  print(inventory)
出力: 50期待: 80 (エラーにはなりません)

在庫を入れ替える関数でも同じです。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)
出力: 20期待: 0 (エラーにはなりません)

値を置き換えるだけの単純な関数でも、global宣言を忘れると外側の変数には反映されません。

直し方: (空) を global temperature にします。

この問題を解いてみる →

よくある誤解

エラーは一切出ません。関数は正常に実行され、意図した処理をしたように見えますが、外側の変数は変わらないままという、気づきにくい種類のバグです。

実務での勘所

読み取りには宣言が要らないのに書き込みだけglobal宣言が必要という非対称は、Pythonの「暗黙より明示を」という設計思想(The Zen of Pythonの一節)によるものです。もし宣言なしで書き込みも許してしまうと、うっかり同名のローカル変数のつもりで書いたコードがグローバル変数を意図せず書き換えてしまう事故が起きやすくなります。なお、関数の中の関数(クロージャ)から1つ外側の関数のローカル変数を書き換えたい場合は、globalではなくnonlocalという別のキーワードを使います。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)