Python♪変数や関数の定義位置について整理してみました

Pythonでは、「変数や関数はその変数や関数が実際に使用されるまでに定義されればよい」というのが原則です。しかし、この原則から外れる場合があったり、関数のスコープに気を付けなければ、定義の位置を勘違いしてしまうことがあったりします。そこで、この記事では変数や関数の定義位置について整理してみたいと思います。

0.チュートリアル学習のポイントシリーズ

この記事は「Pythonチュートリアルのポイント整理シリーズ」の記事です。一連の記事は、以下のリンク集を参照してください。
「Pythonチュートリアル」のポイント整理シリーズ

1.変数の定義位置の簡単な例

関数や変数の定義は、関数や変数を実際に実行するまでに定義する必要があります。コード01は問題なく実行されますが、コード02はエラーになります。「こんな簡単な例題なんて必要ない。馬鹿にするな。」と言われそうですね。でも、順を追って説明しますので、少し、我慢してください。

#コード01
x = 10
print(x)
#コード02 →エラー
print(x)
x = 10

2.関数の定義位置の簡単な例

次に、関数の定義位置についてみてみましょう。Pythonではコード03は問題ありませんが、コード04はエラーになります。関数についてはコード04のような書き方ができるプログラミング言語もありますので、他のプログラミング言語の経験がある人は注意が必要です。

Pythonのインタプリタは、コード全体を理解したあとに実行するのではなく、前から順番にコードを理解しながら実行します。ですから、コード03のように2~3行目で関数xxx()がどのような関数であるかを理解したあとならば5行目のxxx()を実行できますが、コード04のように、いきなり最初の行にxxx()が現れても、Pythonはxxx()がどんな関数なのかを理解できません。これは、コード02がエラーになるのと似ています。

#コード03
def xxx():
    print('xxx')

xxx()
#コード04 →エラー
xxx()

def xxx():
    print('xxx')

3.変数の定義位置の原則

グローバル変数であってもローカル変数であっても、複雑な入れ子構造の関数の中であっても、「変数はその変数が実際に使用されるまでに定義されればよい」というのが原則です。

実際に関数の中のグローバル変数について検証してみます。コード05~08の関数xxx()の中の変数aはグローバル変数です。コード05、コード06はエラーにはなりませんが、コード07はエラーになります。

関数xxx()の中のグローバル変数は、関数xxx()が定義される前に定義する必要はなく、実際に変数aが使用されるまでにaの値を定義すれば問題ありません。しかし、コード07のように、5行目のxxx()のあとに変数aを定義すると、変数aの使用時にaの値が定義されていないためにエラーになります。

#コード05
a = 1
def xxx():
    print('a =', a)
 
xxx()
#コード06
def xxx():
    print('a =', a)
 
a = 2
xxx()
#コード07 →エラー
def xxx():
    print('a =', a)
 
xxx()
a = 3

また、コード08の例ではa = 2 が出力されます。2行目ではa = 1ですが、6行目でa = 2となります。したがって、7行目でxxx()が呼び出されるときにはグローバル変数であるaはa= 2になっているのです。

#コード08
a = 1
def xxx():
    print('a =', a)
 
a = 2
xxx()
a = 3
#出力08
a = 2

4.関数の引数のディフォルト値の変数指定は原則から外れる

「変数はその変数が実際に使用されるまでに定義されればよい」というのが原則ですが、実は例外が存在します。それは、関数の引数のディフォルト値を変数で指定するときです。コード09は関数xxx()の引数xのディフォルト値を変数aで指定しています。したがって、関数xxx()を定義している3行目までに変数aを定義する必要があります。

#コード09
a = 1
def xxx(x = a):
    print('x =', x)
 
xxx()

コード10のように、関数を実行する前に変数aの定義を行ったとしても、エラーになります。関数の引数のディフォルト値を変数で指定するときだけは、「変数はその変数が実際に使用されるまでに定義されればよい」というのが原則から外れ、「関数の定義を行うまでに変数を定義する必要がある」となります。

#コード10 →エラー
def xxx(x = a):
    print('x =', x)
 
a = 2
xxx()
#出力10
NameError: name 'a' is not defined

関数の引数のディフォルト値について分かりにくい方は、以下の記事も参考にしてみてください。

引数のディフォルト値が変化する場合と変化しない場合の違い

5.関数の定義位置の原則

関数も変数と同じく実際に関数が実行されるまでに定義されていればよく、コード11のようにyyy()のあとにxxx()があっても、9行目でyyy()が実行されるときには5~6行目で関数xxx()の定義が終了しているので問題ありません。

#コード11
def yyy():
    xxx() 

def xxx():
    print('a =', a)

a = 1
yyy()

コード12は関数yyy()の定義5~6行目の前に、3行目で関数yyy()を呼び出した例です。関数呼び出し時に関数が定義されていないのでエラーになります。

#コード12 →エラー
a = 1
yyy()

def yyy():
    xxx()

def xxx():
    print('a =', a)

入れ子構造の関数の場合でも同じです。コード13は問題ありませんが、コード14はエラーになります。

#コード13
a = 1
def yyy():
    def xxx():
        print('a =',a)
    xxx()

yyy()
#コード14 →エラー
a = 1
def yyy():
    xxx()
    def xxx():
        print('a =',a)

yyy()

6.関数内の変数のスコープは関数の定義時に決定する

関数内の変数がグローバル変数なのか、ローカル変数なのかは関数の実行時ではなく、関数の定義時に決定します。

コード15では、関数yyy()が2~6行目で定義されていますが、6行目にa = 2とありますので、yyy()のaはローカル変数となります。したがって、yyy()の中にある関数xxx()の変数aは、関数yyy()のローカル変数を参照することになります。これは、yyy()の定義時に確定します。つまり、8行目のグローバル変数a = 1をxxx()から参照することはありません。

しかし、6行目のa =2 は5行目のxxx()よりも後に定義されているので、xxx()実行時にaの値は定義されていないことになり、コード15はエラーになります。

#コード15 →エラー
def yyy():
    def xxx():
        print('a =', a)
    xxx() 
    a = 2

a = 1
yyy()

コード15は、コード16のようにすればエラーになりません。

#コード16
def yyy():
    a = 2
    def xxx():
        print('a =', a)
    xxx() 
a = 1
yyy()

コード15がエラーになる理由がわかりにくい方は、以下の記事を参考にしてください。

関数で変なエラーが出た:localvariable ‘x’ referenced before assignment

数や変数の定義位置について、なんとなく理解したつもりになっていた人もいたのではないでしょうか。この機会に定義位置についての考え方を整理してみては、いかがでしょうか。