Pythonにおける名前空間とスコープ

プログラミング言語の変数や関数などの名前は、名前空間とスコープによって管理されています。今回は Python における名前空間とスコープについて具体的な例を用いながら説明していきます。

名前空間とは

名前空間とは、ある変数や関数が所属している場所のことを示します。変数は所属する名前空間の中でしか、値を参照したり代入したりすることはできません。たとえば、ある関数を定義し、その関数内で変数を定義した場合、この変数は関数の外から値を参照したり代入したりすることはできません。これは変数がその関数内に存在する名前空間に所属しているからです。

スコープとは

スコープとは、ある変数や関数が有効な範囲を示します。その変数や関数が有効な範囲は、それらがどの名前空間に所属しているかに依存します。たとえば、関数内のスコープで定義された変数は、上位の名前空間で定義された変数を参照することはできますが、その変数に代入(上書き)することはできません。たとえ同じ名前の変数でも、関数内定義された変数は関数外とは別物として扱われています。

以下では、Python におけるスコープについて詳しく説明していきます。

Python におけるスコープは大きく分けて3通りのスコープが存在します。ビルトインスコープ、モジュールスコープ、ローカルスコープです。

ビルトインスコープ

ビルトインスコープは、組み込み関数や組み込み変数のスコープを示します。たとえば max, None などのスコープが挙げられます。ビルトインスコープはプログラムの全体で有効なので、このスコープで定義されている関数や変数は特にインポートなどはせず、意識することなくプログラム内で参照することができます。

モジュールスコープ

モジュールスコープとは、モジュールのトップレベルで定義されるスコープで、一番上位のスコープになります。Python におけるモジュールは Python の定義や文が入ったスクリプトファイルであり、モジュールスコープはスクリプトファイル内全体に影響があります。モジュールスコープでは変数や関数を自由に定義することができます。

ローカルスコープ

ローカルスコープとは、定義された関数内でのみ作られるスコープです。ローカルスコープで定義された変数や関数は、トップレベルのモジュールからは参照できません。また、if 文や for 文などの制御構文ではローカルスコープは作られません。

スコープに関するサンプル

具体的なプログラムを用いてスコープについて説明していきます。

# -*- coding: utf-8 -*-

a = 1       # モジュールスコープに定義された変数 a
def test(): # モジュールスコープに定義された関数 test
    a = 10  # ローカルスコープに定義された変数 a
    print(a)

test() # 10
print(a) # 1

上のプログラムでは、関数外で定義された a と test() 関数内で定義された a は別のものとして扱われます。これはローカルスコープで定義された変数はそのスコープでしか影響を及ぼさないからです。

その証拠に test() を呼び出したときは、test() 関数内での a 、すなわちローカルモジュール内で定義された a を参照し 10 と表示されているのに対して、 関数を抜けた後で print(a) を実行したときはモジュールスコープで定義された a が参照され 1 が表示されています。

次は if 文の制御構造を用いた例を見てみましょう。

if True:
    x = 1

print x # 1

Python では if 文などの制御構造でもスコープが変わらないので、 if 文のブロック内で初めて定義された変数は、そのブロックを抜けた後でも参照することができます。

a = 1
if a == 1:
    a = 2
    print(a) # 2

print(a) # 2

この例の場合は、if文 の内側と外側もスコープが変わらないので、両方とも同じ a を参照しており 2 が表示されています。

for 文の例を見てみましょう。

a = [1, 2, 3]
x = 1
for x in a
    print x

print x

実行結果

1
2
3
3

for 文の場合も if 文のときと同様、内側も外側もスコープが変わらないので、 両方とも同じ x を参照しており、最後に x に代入された値 3 が表示されています。

まとめ

Python のスコープはシンプルであり、基本的には関数内で定義された変数は、その内側でのみ参照できます。スコープの扱いはプログラミング言語ごとに異なる場合があるので、きちんとその言語のスコープの定義を理解しておきましょう。

ちなみにPyrhon には今回説明したスコープの動作を変更し、関数内でグローバルな変数を定義する方法があります。グローバル変数を定義する方法については「Pythonでのグローバル変数の宣言方法」の記事を参照してください。


イベント