Exemple simple. Deux méthodes, l'une appelée depuis une autre:
def method_a(arg):
some_data = method_b(arg)
def method_b(arg):
return some_data
En Python, nous pouvons déclarer def
dans un autre def
. Donc, si method_b
est requis et appelé uniquement depuis method_a
, dois-je déclarer à l' method_b
intérieur method_a
? comme ça :
def method_a(arg):
def method_b(arg):
return some_data
some_data = method_b(arg)
Ou devrais-je éviter de faire ça?
python
coding-style
nukl
la source
la source
method_b
? (@inspector: Vous en avez besoin, à proprement parler, mais c'est extrêmement utile lorsque vous entrez dans un peu de programmation fonctionnelle, en particulier des fermetures).Réponses:
Est ce que c'est ce que vous recherchiez? Cela s'appelle une fermeture .
la source
do_it()
qui est probablement un peu plus compliqué que ce qui peut être géré par une certaine arithmétique dans une seulereturn
instruction.Vous ne gagnez pas vraiment grand-chose en faisant cela, en fait cela ralentit
method_a
car il définira et recompilera l'autre fonction à chaque fois qu'elle sera appelée. Compte tenu de cela, il serait probablement préférable de simplement préfixer le nom de la fonction avec un trait de soulignement pour indiquer que c'est une méthode privée - c'est-à-dire_method_b
.Je suppose que vous voudrez peut -être faire cela si la définition de la fonction imbriquée variait à chaque fois pour une raison quelconque, mais cela peut indiquer un défaut dans votre conception. Cela dit, il existe une raison valable de le faire pour permettre à la fonction imbriquée d'utiliser des arguments qui ont été passés à la fonction externe mais qui ne leur ont pas été explicitement transmis, ce qui se produit parfois lors de l'écriture de décorateurs de fonction, par exemple. C'est ce qui est montré dans la réponse acceptée bien qu'un décorateur ne soit pas défini ou utilisé.
Mettre à jour:
Voici la preuve que leur imbrication est plus lente (en utilisant Python 3.6.1), bien que certes pas de beaucoup dans ce cas trivial:
Remarque J'ai ajouté quelques
self
arguments à vos exemples de fonctions pour les rendre plus comme des méthodes réelles (bien que cemethod_b2
ne soit toujours pas techniquement une méthode de laTest
classe). La fonction imbriquée est également appelée dans cette version, contrairement à la vôtre.la source
method_b = self._method_b
, puis en appelantmethod_b
pour éviter les recherches d'attributs répétées. (Il se trouve que j'ai fait BEAUCOUP de timing ces derniers temps. :)Une fonction à l'intérieur d'une fonction est couramment utilisée pour les fermetures .
(Il y a beaucoup de désaccord sur ce qui fait exactement d' une fermeture une fermeture .)
Voici un exemple utilisant le fichier
sum()
. Il définitstart
une fois et l'utilise à partir de là:Utilisé:
Fermeture en python intégrée
functools.partial
est un exemple de fermeture.D'après la documentation python , c'est à peu près équivalent à:
(Félicitations à @ user225312 ci-dessous pour la réponse. Je trouve cet exemple plus facile à comprendre et j'espère que cela aidera à répondre au commentaire de @ mango.)
la source
En général, non, ne définissez pas les fonctions à l'intérieur des fonctions.
Sauf si vous avez une très bonne raison. Ce que vous ne faites pas.
Pourquoi pas?
lambda
expression à la place .Quelle est vraiment une bonne raison de définir des fonctions à l'intérieur de fonctions?
Quand ce que vous voulez vraiment, c'est une fermeture dingdang .
la source
Il est en fait bien de déclarer une fonction dans une autre. Ceci est particulièrement utile pour créer des décorateurs.
Cependant, en règle générale, si la fonction est complexe (plus de 10 lignes), il peut être préférable de la déclarer au niveau du module.
la source
J'ai trouvé cette question parce que je voulais poser une question pourquoi il y a un impact sur les performances si l'on utilise des fonctions imbriquées. J'ai effectué des tests pour les fonctions suivantes en utilisant Python 3.2.5 sur un ordinateur portable Windows avec un processeur Intel i5-2530M Quad Core 2,5 GHz
J'ai mesuré les 20 fois suivantes, également pour square1, square2 et square5:
et a obtenu les résultats suivants
square0
n'a pas de fonction imbriquée,square1
a une fonction imbriquée,square2
a deux fonctions imbriquées etsquare5
a cinq fonctions imbriquées. Les fonctions imbriquées sont uniquement déclarées mais pas appelées.Donc, si vous avez défini 5 fonctions imbriquées dans une fonction que vous n'appelez pas, le temps d'exécution de la fonction est le double de la fonction sans fonction imbriquée. Je pense qu'il faut être prudent lors de l'utilisation de fonctions imbriquées.
Le fichier Python pour l'ensemble du test qui génère cette sortie se trouve sur ideone .
la source
C'est juste un principe sur les API d'exposition.
En utilisant python, c'est une bonne idée d'éviter l'exposition des API dans l'espace (module ou classe), la fonction est un bon endroit d'encapsulation.
Cela pourrait être une bonne idée. quand tu t'assures
Même si, une utilisation abusive de cette technique peut causer des problèmes et implique un défaut de conception.
Juste à partir de mon exp, peut-être mal compris votre question.
la source
Donc, en fin de compte, il s'agit en grande partie de savoir à quel point l'implémentation de python est intelligente ou non, en particulier dans le cas où la fonction interne n'est pas une fermeture mais simplement une aide nécessaire uniquement.
Dans une conception claire et compréhensible, avoir des fonctions uniquement là où elles sont nécessaires et non exposées ailleurs est une bonne conception, qu'elles soient intégrées dans un module, une classe en tant que méthode, ou dans une autre fonction ou méthode. Lorsqu'elles sont bien faites, elles améliorent vraiment la clarté du code.
Et lorsque la fonction interne est une fermeture, cela peut également aider un peu à la clarté, même si cette fonction n'est pas renvoyée par la fonction conteneur pour une utilisation ailleurs.
Je dirais donc que généralement, utilisez-les, mais soyez conscient de l'impact possible sur les performances lorsque vous êtes réellement préoccupé par les performances et ne les supprimez que si vous effectuez un profilage réel qui montre qu'il vaut mieux les supprimer.
Ne faites pas d'optimisation prématurée en utilisant simplement des «fonctions internes BAD» dans tout le code python que vous écrivez. S'il vous plaît.
la source
C'est parfaitement normal de le faire de cette façon, mais à moins que vous n'ayez besoin d'utiliser une fermeture ou de renvoyer la fonction, je mettrais probablement au niveau du module. J'imagine que dans le deuxième exemple de code, vous voulez dire:
sinon, some_data sera la fonction.
L'avoir au niveau du module permettra à d'autres fonctions d'utiliser method_b () et si vous utilisez quelque chose comme Sphinx (et autodoc) pour la documentation, cela vous permettra également de documenter method_b.
Vous pouvez également envisager de simplement placer la fonctionnalité dans deux méthodes dans une classe si vous faites quelque chose qui peut être représentable par un objet. Cela contient également de la logique si c'est tout ce que vous recherchez.
la source
Faites quelque chose comme:
si vous deviez l'exécuter,
some_function()
il fonctionnerait alorssome_other_function()
et renvoie 42.EDIT: J'ai initialement déclaré que vous ne devriez pas définir une fonction à l'intérieur d'une autre, mais il a été souligné qu'il est parfois pratique de le faire.
la source
Vous pouvez l'utiliser pour éviter de définir des variables globales. Cela vous donne une alternative aux autres modèles. 3 designs présentant une solution à un problème.
A) Utilisation de fonctions sans globaux
B) Utilisation de fonctions avec des globaux
C) Utilisation de fonctions dans une autre fonction
La solution C) permet d'utiliser des variables dans le cadre de la fonction externe sans avoir besoin de les déclarer dans la fonction interne. Peut être utile dans certaines situations.
la source
Fonction In function python
la source