[Python] 正しくない global の使い方

Pythonは名前だらけでは、Pythonの変数も関数も結局はみんな名前、という解説をしました。この特徴を使って、Pythonのちょっとおもしろい挙動を調べてみましょう。

Pythonの変数には、グローバル変数とローカル変数があります。関数の内部で定義した変数はローカル変数、それ以外はグローバル変数となります。

global_var = "これはグローバル変数です。"

def func():
    local_var = "これはローカル変数です"

グローバル変数は同じモジュール内なら誰でも参照できますが、ローカル変数は関数内部でしか参照できません。

また、関数の内部で定義した変数でも、global と宣言された変数はグローバル変数になります。

In [19]:
variable = "これはグローバル変数です。"
def func():
    global variable
    variable = "グローバル変数を更新しました!"

ここで、func() を呼び出す前の variable の値は、 "これはグローバル変数です。" です。

In [20]:
print(variable)
これはグローバル変数です。

func() を呼び出すと、グローバル変数 variable は更新されて、 "グローバル変数を更新しました!"になります。

In [21]:
func()
print(variable)
グローバル変数を更新しました!

ここまでは、普通の global 宣言の使い方ですね。

ローカルでグローバルな関数

では、こんどはこんな関数をみてみましょう。

In [49]:
def func():
    def local_func():
        print("ローカル関数です!")

関数 func() の中で、もう一つの関数 local_func() を定義しています。普通の変数とおなじように、local_func() もローカル変数と同じ扱いで、関数 func() 内からしか呼び出せません。

では、local_func という名前を global 宣言するとどうなるでしょう?

In [23]:
def func():
    global local_func
    def local_func():
        print("ローカル関数です!")

Pythonは名前だらけでしつこく繰り返しましたが、Pythonでは変数の代入も関数の定義も、結局は名前を定義するだけのことです。関数定義でできた名前も、変数の定義と同じ仕組みで処理されます。

ということは、func()を実行すると……

In [24]:
func()
local_func()
ローカル関数です!

関数名 local_func も、普通の変数と同じようにグローバル変数となり、関数の外側からも呼び出せるようになりました。

def func():
    global local_func
    def local_func():
        print("ローカル関数です!")

という処理は、

def func():
    def work_file_name():
        print("ローカル関数です!")

    global local_func
    local_func = work_file_name

と同様、と考えるとわかりやすいかもしれません。

あまり意味のないglobalの使い方ですが、Pythonが変数定義も関数定義も区別していない、ということがよく分かると思います。

import 文でも、同じような使い方ができます。変数名 sysglobal宣言してから、 標準モジュール sys をインポートするとどうなるでしょう?

In [50]:
def func():
    global sys  # 変数名 sys をグローバル宣言
    import sys  # sys をインポート

func()
print(sys)
<module 'sys' (built-in)>

nonlocal 宣言

Pythonにはもう一つ、nonlocal という宣言というのがあります。こちらはローカル関数の中で変数を定義したとき、ローカル変数ではなく、その関数の外側のローカル変数を変更する、という宣言です。

In [40]:
def func():
    var1 = 1
    var2 = 2
    
    def local_func():
        nonlocal var2
        var1 = "three" # local_func の var1 を更新
        var2 = "four"  # 外側の var2 を更新
    
    local_func()
    print(f'{var1=}; {var2=}')

func()
var1=1; var2='four'

ローカル関数 local_func() では var1var2 を更新していますが、var2nonlocal と宣言しているので、外側で定義された変数 var2 を更新します

これも関数定義でやってみましょう。

In [ ]:
def func():
    var1 = 1
    
    def local_func():
        nonlocal var1  # 外側の var1 を更新
    
        def var1():    # 関数 var1 を定義
            print("Hi!")
    
    local_func()
    var1()

ローカル関数内で変数 var1nonlocal と宣言し、同じ名前で関数を定義しました。実行するとどうなるか、もうおわかりですね?

In [48]:
func()
Hi!

local_func() では変数名 var1nonlocal と宣言していますから、var1 という名前の関数を作ると、当然外側の var1 が更新される、という寸法です。おっかないですね!

注意!

このページで紹介した globalnonlocal の使い方は、Pythonの名前の扱い方を紹介するためのサンプルです。普通のプログラムではまず使うことはありません。 Don't try this at home, Kids!