88926


Python3での関数内関数の用途に関する質問です．

関数A内で定義された関数Bがあり，その外側の関数Aが実行されるたびに関数Bのオブジェクトが生成されます．

[Pythonの関数内関数の利点は何ですか？ - teratail](https://teratail.com/questions/345017)

関数Bを関数A以外で用いる予定がない場合は，関数Aの中で定義しておくべきでしょうか．それともオブジェクトの多重生成を避けるために，関数の外で定義するべきでしょうか．

以下はフィボナッチ数列の第n項を返す関数の例です．

[code]

    sqrt = lambda x: x**.5
    def fibo(n):
        return round((((1+sqrt(5))/2)**n - ((1-sqrt(5))/2)) / sqrt(5))
    
[/code]

[code]

    def fibo(n):
        sqrt = lambda x: x**.5
        return round((((1+sqrt(5))/2)**n - ((1-sqrt(5))/2)) / sqrt(5))
    
[/code]


CC BY-SA 4.0
2022-05-19T00:38:05.217
88911
2022-05-19T15:53:40.987
2022-05-19T04:36:03.147
3060
51374
question
python python3
関数内関数はいつ用いるべきか


どちらがよいか一概に言えないと思います。

  * 名前の競合を減らすため、関数の中で定義
  * 性能が問題になりそうなら、関数の外で定義

性能が問題になるかは計測してみないと分かりません。個人的な意見ですが関数の中で定義しておき、問題があるようなら対応を考えます。


CC BY-SA 4.0
2022-05-19T12:15:10.143
88924
2022-05-19T12:15:10.143
35558
88911
answer


「Pythonの関数内関数の利点」の Q＆A は,  
Pythonでの closure(クロージャー)の話であり, トップレベルで関数定義する場合と異なり呼び出すたび生成される というだけです。

Pythonの関数定義は, トップレベルだろうと関数内からであろうと その時点で生成されるので, (別の, 例えば) 変数に何かしらの演算結果を代入する
ことと同じように考えてよいでしょう。

関数呼び出しのたびに毎回演算行うか, 一度演算しておいて結果だけ毎回利用するか … の違い。  
outerの関数の呼び出しが多いか少ないか (で, 多少パフォーマンスが異なる)

[code]

    import dis
    
    src = '''
    def fn():
        pass
    def outer_fnc():
        def inner_fnc():
            pass
    '''
    dis.dis(src)
    
[/code]

上記の(文字列内の)ソースでは, `fn`, `inner_fnc` (と `outer_fnc`) が定義されていて, そのポイントを通る際
`MAKE_FUNCTION` が実行され, `STORE_NAME` (あるいは `STORE_FAST`) される。

[code]

      2           0 LOAD_CONST               0 (<code object fn at 0x7fc33fd42a50, file "<dis>", line 2>)
                  2 LOAD_CONST               1 ('fn')
                  4 MAKE_FUNCTION            0
                  6 STORE_NAME               0 (fn)
    
      4           8 LOAD_CONST               2 (<code object outer_fnc at 0x7fc33fd42030, file "<dis>", line 4>)
                 10 LOAD_CONST               3 ('outer_fnc')
                 12 MAKE_FUNCTION            0
                 14 STORE_NAME               1 (outer_fnc)
                 16 LOAD_CONST               4 (None)
                 18 RETURN_VALUE
    
    Disassembly of <code object fn at 0x7fc33fd42a50, file "<dis>", line 2>:
      3           0 LOAD_CONST               0 (None)
                  2 RETURN_VALUE
    
    Disassembly of <code object outer_fnc at 0x7fc33fd42030, file "<dis>", line 4>:
      5           0 LOAD_CONST               1 (<code object inner_fnc at 0x7fc33fd42390, file "<dis>", line 5>)
                  2 LOAD_CONST               2 ('outer_fnc.<locals>.inner_fnc')
                  4 MAKE_FUNCTION            0
                  6 STORE_FAST               0 (inner_fnc)
                  8 LOAD_CONST               0 (None)
                 10 RETURN_VALUE
    
    Disassembly of <code object inner_fnc at 0x7fc33fd42390, file "<dis>", line 5>:
      6           0 LOAD_CONST               0 (None)
                  2 RETURN_VALUE
    
[/code]

関数内かどうかで多少変化あるように見えるけど, それは普通の変数でも同じ  
(`STORE_NAME`, `STORE_FAST` の速度は多少異なるので, 速度気にするなら調べたほうがよいかも)

[code]

    src = '''
    n = 10
    val = 2 **n
    def fn():
        val = 2 **n
        return val
    '''
    dis.dis(src)
    
[/code]

[code]

      2           0 LOAD_CONST               0 (10)
                  2 STORE_NAME               0 (n)
    
      3           4 LOAD_CONST               1 (2)
                  6 LOAD_NAME                0 (n)
                  8 BINARY_POWER
                 10 STORE_NAME               1 (val)
    
      4          12 LOAD_CONST               2 (<code object fn at 0x7fc33fd3fb70, file "<dis>", line 4>)
                 14 LOAD_CONST               3 ('fn')
                 16 MAKE_FUNCTION            0
                 18 STORE_NAME               2 (fn)
                 20 LOAD_CONST               4 (None)
                 22 RETURN_VALUE
    
    Disassembly of <code object fn at 0x7fc33fd3fb70, file "<dis>", line 4>:
      5           0 LOAD_CONST               1 (2)
                  2 LOAD_GLOBAL              0 (n)
                  4 BINARY_POWER
                  6 STORE_FAST               0 (val)
    
      6           8 LOAD_FAST                0 (val)
                 10 RETURN_VALUE
    
[/code]


CC BY-SA 4.0
2022-05-19T15:53:40.987
88926
2022-05-19T15:53:40.987
43025
88911
answer