Función anidada en Python

¿Qué beneficio o implicaciones podríamos obtener con el código Python de esta manera?

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

Encontré esto en un proyecto de código abierto, haciendo algo útil dentro de la función anidada, pero no haciendo absolutamente nada fuera de él excepto llamándolo. (El código real se puede encontrar aquí .) ¿Por qué alguien podría codificarlo así? ¿Hay algún beneficio o efecto secundario para escribir el código dentro de la función anidada en lugar de en la función normal externa?

Related of "Función anidada en Python"

Normalmente lo haces para hacer cierres :

 def make_adder(x): def add(y): return x + y return add plus5 = make_adder(5) print(plus5(12)) # prints 17 

Las funciones internas pueden acceder a las variables desde el ámbito adjunto (en este caso, la variable local x ). Si no está accediendo a ninguna variable del ámbito adjunto, en realidad son solo funciones ordinarias con un scope diferente.

Aparte de los generadores de funciones, donde la creación de funciones internas es casi la definición de un generador de funciones, la razón por la que creo funciones anidadas es para mejorar la legibilidad. Si tengo una pequeña función que solo será invocada por la función externa, entonces inserto la definición para que no tenga que saltar para determinar qué está haciendo esa función. Siempre puedo mover el método interno fuera del método de encapsulación si encuentro la necesidad de reutilizar la función en una fecha posterior.

Ejemplo de juguete:

 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() 

Un beneficio potencial del uso de métodos internos es que le permite usar las variables locales del método externo sin pasarlas como argumentos.

 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) 

Se puede escribir de la siguiente manera, lo que podría decirse que es mejor

 def save(item, resultBuffer): def helper(feature): resultBuffer.print(feature) resultBuffer.printLine() resultBuffer.flush() helper(item.description) helper(item.size) helper(item.type) 

No puedo imaginar ninguna buena razón para un código como ese.

Tal vez había una razón para la función interna en las revisiones anteriores, como otras operaciones.

Por ejemplo, esto tiene un poco más de sentido:

 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) 

pero entonces la función interna debería ser los métodos de clase (“privados”) en su lugar:

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

La idea detrás de los métodos locales es similar a las variables locales: no contamine el espacio de nombres más grande. Obviamente, los beneficios son limitados, ya que la mayoría de los lenguajes no proporcionan dicha funcionalidad directamente.

¿Estás seguro de que el código era exactamente así? La razón normal para hacer algo como esto es para crear una parcial, una función con parámetros horneados. Llamar a la función externa devuelve un llamable que no necesita parámetros, por lo que, por lo tanto, se puede almacenar y utilizar en cualquier lugar donde sea imposible pasar parámetros. Sin embargo, el código que ha publicado no lo hará: llama a la función de inmediato y devuelve el resultado, en lugar del código que se puede llamar. Podría ser útil publicar el código real que viste.