90 votes

Fonction imbriquée en Python

Quels sont les avantages ou les conséquences pourrions-nous obtenir avec Python code comme ceci:

class some_class(parent_class):
    def doOp(self, x, y):
        def add(x, y):
            return x + y
        return add(x, y)

J'ai trouvé ça dans un projet open-source, faire quelque chose d'utile à l'intérieur de la fonction imbriquée, mais ne faisant absolument rien en dehors de lui, sauf en l'appelant. (Le code peut être trouvé ici.) Pourquoi aurait-on code comme ceci? Est-il un avantage ou un effet secondaire de l'écriture du code à l'intérieur de la fonction imbriquée plutôt qu'à l'extérieur, la fonction normale?

120voto

Adam Rosenfield Points 176408

Normalement vous le faites pour faire des fermetures :

 def make_adder(x):
    def add(y):
        return x + y
    return add

plus5 = make_adder(5)
print(plus5(12))  # prints 17
 

Les fonctions internes peuvent accéder aux variables à partir de la portée englobante (dans ce cas, la variable locale x ). Si vous n'accédez à aucune variable de la portée englobante, il ne s'agit en réalité que de fonctions ordinaires avec une portée différente.

63voto

Ross Rogers Points 5619

Outre des générateurs de fonction, où la fonction interne création est presque la définition d'un générateur de fonction, la raison pour laquelle je créer des listes de fonctions est d'améliorer la lisibilité. Si j'ai une petite fonction qui va être appelée par la fonction externe, puis j'ai inline la définition de sorte que vous n'avez pas à sauter pour déterminer ce que la fonction est en train de faire. Je peux toujours aller de l'intérieur de la méthode à l'extérieur de l'encapsulation méthode si je trouve un besoin de réutiliser la fonction à une date ultérieure.

Jouet exemple:

import sys

def Foo():
    def e(s):
        sys.stderr.write('ERROR: ')
        sys.stderr.write(s)
        sys.stderr.write('\n')
    e('I regret to inform you')
    e('that a shameful thing has happened.')
    e('Thus, I must issue this desultory message')
    e('across numerous lines.')
Foo()

27voto

Kuba Points 734

L’utilisation des méthodes internes présente l’avantage potentiel de vous permettre d’utiliser des variables locales de méthodes externes sans les transmettre en tant qu’arguments.

 def helper(feature, resultBuffer):
  resultBuffer.print(feature)
  resultBuffer.printLine()
  resultBuffer.flush()

def save(item, resultBuffer):

  helper(item.description, resultBuffer)
  helper(item.size, resultBuffer)
  helper(item.type, resultBuffer)
 

peut être écrit comme suit, qui se lit sans doute mieux

 def save(item, resultBuffer):

  def helper(feature):
    resultBuffer.print(feature)
    resultBuffer.printLine()
    resultBuffer.flush()

  helper(item.description)
  helper(item.size)
  helper(item.type)
 

8voto

Jochen Ritzel Points 42916

Je ne peux pas imaginer une bonne raison pour un code comme ça.

Peut-être y avait-il une raison pour la fonction interne dans les révisions plus anciennes, comme dans les autres opérations.

Par exemple, cela a un peu plus de sens:

 class some_class(parent_class):
    def doOp(self, op, x, y):
        def add(x, y):
            return x + y
        def sub(x,y):
            return x - y
        return locals()[op](x,y)

some_class().doOp('add', 1,2)
 

mais alors la fonction interne devrait être des méthodes de classe ("privées"):

 class some_class(object):
    def _add(self, x, y):
        return x + y
    def doOp(self, x, y):
        return self._add(x,y)
 

6voto

avguchenko Points 1518

L'idée derrière les méthodes locales est similaire aux variables locales: ne polluez pas l'espace de noms plus grand. Évidemment, les avantages sont limités car la plupart des langues ne fournissent pas directement une telle fonctionnalité.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X