J'étais aussi curieux à ce sujet, alors j'ai décidé de trouver combien les frais généraux ainsi encourus. En résumé, la réponse est peu de chose.
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from timeit import timeit
>>> def subfunc():
... pass
...
>>> def no_inner():
... return subfunc()
...
>>> def with_inner():
... def s():
... pass
... return s()
...
>>> timeit('[no_inner() for _ in range(1000000)]', setup='from __main__ import no_inner', number=1)
0.22971350199986773
>>> timeit('[with_inner() for _ in range(1000000)]', setup='from __main__ import with_inner', number=1)
0.2847519510000893
Mon instinct m'a poussé à regarder les pourcentages (with_inner est 24% plus lent), mais ce chiffre est trompeur dans ce cas, puisque nous ne retournerons jamais la valeur d'une fonction interne à partir d'une fonction externe, surtout avec des fonctions qui ne font rien.
Après avoir fait cette erreur, j'ai décidé de la comparer à d'autres choses courantes, pour voir quand cela a de l'importance et quand cela n'en a pas :
>>> def no_inner():
... a = {}
... return subfunc()
...
>>> timeit('[no_inner() for _ in range(1000000)]', setup='from __main__ import no_inner', number=1)
0.3099582109998664
En regardant cela, nous pouvons voir que cela prend moins de temps que de créer un dict vide ( la méthode rapide ), donc si vous faites quelque chose de non trivial, cela n'a probablement pas d'importance du tout.