Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Python入門と関数のネスト

Pythonでの関数のネスト(入れ子)についての解説。デコレーターを理解するための前提

Pythonと関数のネストについての解説。デコレーターを理解するための前提として重要な知識について説明。

今回はPythonにおける、いわゆる「関数のネスト」というものをPythonプログラミング初心者に向けた解説です。

今回の解説する基本知識は、Pythonで大きな効果を発揮するデコレーターという機能を理解するための前提となる重要な知識です。時間をかけてのんびり読んでみてください。

そのデコレーターについては、「【Python入門】デコレータの基本をわかりやすく解説」を作っていますので、今回の記事を読んだ後にでも読んでみてください。

関数のネストとは?

まずネストというのは英語「nest」で、その本来の意味は巣とか巣窟とかです。そしてソレ以外にも「入れ子」という意味もあります。

入れ子とは、箱の中に箱があって、その箱の中にまた箱があって・・・みたいな、ロシアのマトリョーシカ人形のような構造になっている状態のことです。

プログラミングではその「入れ子」という意味でよく使われます。

そこで、関数のネストとは大雑把にいえば、次のようなコードの状態になっていることです。

def 関数1():
    def 関数2():
        def 関数3():
            def 関数4():

関数1の内部に関数2が入っていて、その関数2の内部にまた関数3が入ってい、その関数3の内部にまた関数4が入っていて・・・・・・という状態のコードです。

学問レベルのプログラミング(情報工学?コンピューターサイエンス?)ではもっと正確かつ厳密な定義がなされているようですが、実際にプログラミングするときはそんな高度なレベルの知識がなくても問題ないので、ひとまず大雑把に上のような感じで理解すれば十分だと思います。

以下、関数のネストについて今回はreturn文を使った場合の具体例を見ていきましょう。私はそれがデコレーターを理解するためのとても重要な知識になると思っています。

return文で関数の内容を置き換える~デコレーターを理解するための前知識~

基本例1

def fnc_one(int_num):
    return int_num*5

fnc_one(3)  # 結果:15

まず初めに上のコードを見てください。

これは特に問題なく理解できると思います。関数fnc_oneの引数に3が指定されているので、int_numに3が代入され、そして処理が実行されます。

では次にこのコードを少しだけ変更した次の例を見て下さい。

基本例2

def fnc_one(int_num):
    #引数の型をチェックして不適切な場合はエラーメッセージ表示
    assert type(int_num)==int, '整数を実引数に設定してください'
    return print(int_num*5)

fnc_one(3)

まずassert文については「【開発効率UP】Pythonのassert文をわかりやすく解説。if文との比較と使用上の注意点」という記事を読んで見てください。

さて上の基本例1とくらべると、return文の内容として、print()関数になっている点に着目してください。return文の内容は、「関数」です。

そして実際に関数fnc_oneを実行するとprint()関数が動きます。def内部のreturn文で設定された処理が、fnc_oneの処理(中身)になっていると考えられます。

そこで下のコードの形を見てください

def 関数A():
    def 関数B():
    return 関数B()  #def 関数B()と同じインデントの深さであることに注意してください

このようなdef~returnの形のコードの場合は、かなり乱暴に言ってしまうと、

関数A内のreturn文の内容(関数B)=関数Aの内容

になっていると考えてしまっても良いのではないでしょうか。あくまで今回の場合はですが。

ひとまずは、関数Aが、関数Bによって置き換えられるとイメージするといいと思います。

だったら、return文の内容として自分で作った「関数」を設定すれば、それが関数fnc_oneの処理内容ともなるでしょう。

そこで次の例でユーザーが独自に作成した関数を使う場合を考えてみましょう。

基本例3

以下のコードを見てください。

return文の内容として、calculatingという自作の関数を設定しました。

def fnc_one(int_num):
    #実引数の型チェック
    assert type(int_num) == int, '整数を実引数に設定してください'
    
    def calculating(number):
        return number*5)
        
    return calculating(int_num)

fnc_one(3)  # 結果:15

これの処理の流れを解説をしますと、

・fnc_one(3)によって、fnc_oneが実行されます。その引数int_numには3が代入されます。

・assert文で引数の型がチェックされます。

・return calculating(int_num)が実行されます。このint_numには3が入っています。つまり、calculating(3)になっています。

・calculatingの中身はdef calculating~で設定した内容ですので、その引数numberに3(つまりint_numの値)が代入され、結局3×5=15が返ります(渡されます)。

以上のことを簡単に画像にしてみました。

Pythonと関数のネストの解説

いかがでしょうか。

上画像のでいう②のreturn calculating~によって、最終的にfnc_oneの処理の中身が実質的に置き換わっているのがイメージできるでしょうか。

関数A内のreturn文の内容(関数B)=関数Aの内容

ネストされた(ある関数の内部で定義された別の関数)関数で、その外にある関数の内容が置き換えられているというイメージです。

関数のネストとreturn文を使うことで、このように関数の処理内容を書き換える(置き換える)ことが可能なのです。

そしてまさにこれがPythonプログラミングの特徴の1つともいえるデコレーターの理解の前提となります。

なお、辞書のネストについてはこちらの記事をご覧ください。

Pythonで辞書の中に辞書を追加する方法と辞書のネスト化についての初心者向け解説

そして、デコレータについては「【Python入門】デコレータの基本をわかりやすく解説」をご覧ください。

愛を分かち合いましょう