10.1 関数のローカル変数
Pythonでは、変数は作成された瞬間から、そのスコープが終わるまで(通常は変数が宣言された関数内)アクセスできます。すべての関数の外で宣言された変数は、グローバル変数と呼ばれます。
Pythonでの変数のスコープは、変数が使用できる文脈を決定します。スコープは名前の衝突を避け、データへのアクセスを管理します。Pythonの主なスコープのタイプは以下を含みます:
ローカルスコープ: 関数内で作成された変数は、その関数のローカルスコープ内に存在し、その関数内でのみアクセス可能です。
ネストされた関数のスコープ: ある関数の内で定義された関数の変数は、そのネストされた関数内でのみアクセス可能です。
グローバルスコープ: スクリプトやモジュールのレベルで定義された変数はグローバルとされ、同じモジュール内のどの部分からもアクセス可能です。
組み込みスコープ: これは特別なスコープで、すべての組み込みPythonオブジェクトと関数(例: print()やlen())を含んでいます。
LEGBルール
Pythonの変数解決にはLEGBルールが使用され、インタプリタが変数を探す順序を定めています:
- L (Local) — まずローカルスコープで検索。
- E (Enclosed) — 次に、ネストされた関数のスコープ内で最も近いものから外側へ。
- G (Global) — 次にグローバルスコープで。
- B (Built-in) — 最後に組み込みスコープで。
使用例
x = "global" # グローバル変数
def outer():
y = "outer local" # 外側の関数のローカル変数
def inner():
z = "inner local" # ネストされた関数のローカル変数
print(x) # "global"を出力
print(y) # "outer local"を出力
print(z) # "inner local"を出力
inner()
outer()
変数 z
は関数 inner()
内でのみアクセス可能です。
変数 y
は関数 outer()
内と、その内で宣言されたすべての関数内でアクセス可能です。
変数 x
は現在のファイル(モジュール)内のどこからでもアクセス可能です。
10.2 グローバル変数へのアクセス: global x
Pythonの興味深い特徴の一つは、外部のスコープ(現在のスコープにネストされたスコープ)からの変数は読み取りのみ可能であることです。
外部変数に何かを書き込もうとすると、同じ名前のローカル変数が作成され、外部の変数へのアクセスは失われます。
例:
x = 10
def change_global():
print(x) # これはエラーを引き起こす、なぜならxは代入後にローカル変数とみなされるから
x = 20 # ここでローカル変数xが作成される
print(x) # 20を出力(ローカル変数xへのアクセス)
change_global()
print(x) # 10を出力
この例は動作せず、UnboundLocalError
を引き起こします。なぜなら、Pythonのインタプリタはまず x = 20
の代入を見て、x
をローカル変数と見なすからです。しかし、インタプリタが print(x)
の行に到達すると、まだ定義されていないローカル変数 x
を見つけられません。
これは安全のために行われており、ローカル変数が誤ってグローバル変数を変更しないようにするものです。
global
演算子
意識して関数内でグローバル変数の値を変更する必要がある場合、global
演算子を使用できます。この演算子は、変更がローカル変数ではなくグローバル変数で行われるべきであることを明示的に示します。
関数内でグローバル変数の値を変更するためには、関数の先頭でこの変数を global
として宣言する必要があります。これにより、変数への書き込みアクセスが関数に与えられます:
x = 10
def change_global():
global x # xをグローバル変数として宣言
print(x) # 10を出力(グローバル変数xへのアクセス)
x = 20 # グローバル変数xに新しい値を代入
print(x) # 20を出力(グローバル変数xへのアクセス)
change_global()
print(x) # 20を出力
global
演算子の使用により、エラーを避け、グローバル変数を正しく管理できます。
グローバル変数はプログラムを予測不可能にし、理解しにくくする可能性があります。特にプログラムが大きくて、複数のプログラマによって開発されている場合、その影響は重要です。
時にはグローバル変数の使用が避けられない場合もありますが、できるだけその使用を最小限に抑えるよう努めるべきです。グローバル変数の代わりに、関数のパラメータや戻り値、状態を保存するためのクラスを使うことを検討してください。
グローバル変数の使用は、予期しない副作用を引き起こし、コードのデバッグやテストを困難にし、その再利用性を低下させる可能性があります。そのため、グローバル変数は必要な場合にのみ慎重に使用することが推奨されます。
10.3 非ローカル変数へのアクセス: nonlocal
グローバル変数とローカル変数に加えて、Pythonには中間スコープからの変数も存在します。たとえば、関数内に関数がネストされている場合です。これらの変数の操作には nonlocal
演算子を使用します。
nonlocal
演算子は、グローバル変数を除いて、最も近いスコープ内で変数を変更することを可能にします。
nonlocal
演算子は、外部関数で定義された変数を変更する必要がある場合に、ネストされた関数内で新しいローカル変数の作成を避けます。nonlocal
を使用しないと、変更は内部関数のローカル変数にのみ影響し、外部関数の変数には影響しません。
例:
def outer():
count = 0
def inner():
nonlocal count
count += 1
return count
return inner
counter = outer()
print(counter()) # 1を出力
nonlocal
を利用してカウンターを作成する、より実用的な例:
def create_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
counter = create_counter()
print(counter()) # 1を出力
print(counter()) # 2を出力
print(counter()) # 3を出力
この例は、nonlocal
が呼び出し間で状態を保持する関数を作成するためにどのように使われるかを示しています。
GO TO FULL VERSION