Ejemplo simple. Dos métodos, uno llamado desde otro:
def method_a(arg):
some_data = method_b(arg)
def method_b(arg):
return some_data
En Python podemos declarar def
dentro de otro def
. Entonces, si method_b
se requiere y se llama solo desde method_a
, ¿debo declarar method_b
dentro method_a
? Me gusta esto :
def method_a(arg):
def method_b(arg):
return some_data
some_data = method_b(arg)
¿O debería evitar hacer esto?
python
coding-style
nukl
fuente
fuente
method_b
? (@inspector: lo necesita, estrictamente hablando, pero es inmensamente útil cuando entra en un poco de programación funcional, en particular cierres).Respuestas:
Esto es lo que estabas buscando? Se llama cierre .
fuente
do_it()
hace probablemente sería un poco más complicado de lo que puede ser manejado por alguna aritmética en una solareturn
declaración.Realmente no ganas mucho haciendo esto, de hecho se ralentiza
method_a
porque definirá y recompilará la otra función cada vez que se llame. Dado eso, probablemente sería mejor simplemente prefijar el nombre de la función con guión bajo para indicar que es un método privado, es decir_method_b
.Supongo que es posible que desee hacer esto si la definición de la función anidada varía cada vez por alguna razón, pero eso puede indicar una falla en su diseño. Dicho esto, no es una razón válida para hacerlo para permitir la función anidada utilizar argumentos que se pasan a la función exterior, pero no pasa explícitamente a ellos, que a veces ocurre cuando se escribe decoradores de función, por ejemplo. Es lo que se muestra en la respuesta aceptada, aunque un decorador no se define ni se utiliza.
Actualizar:
Aquí hay pruebas de que anidarlos es más lento (usando Python 3.6.1), aunque ciertamente no es mucho en este caso trivial:
Tenga en cuenta que agregué algunos
self
argumentos a sus funciones de muestra para que sean más como métodos reales (aunquemethod_b2
técnicamente todavía no es un método deTest
clase). También la función anidada en realidad se llama en esa versión, a diferencia de la suya.fuente
method_b = self._method_b
y luego llamarmethod_b
para evitar las búsquedas repetidas de atributos. (Sucede que he estado haciendo MUCHO tiempo últimamente. :)Una función dentro de una función se usa comúnmente para cierres .
(Existe una gran controversia sobre qué es exactamente lo que hace que un cierre sea un cierre ).
Aquí hay un ejemplo usando el incorporado
sum()
. Definestart
una vez y lo usa a partir de entonces:En uso:
Cierre de pitón incorporado
functools.partial
Es un ejemplo de cierre.De los documentos de Python , es más o menos equivalente a:
(Felicitaciones a @ user225312 a continuación para obtener la respuesta. Este ejemplo me resulta más fácil de entender y espero que ayude a responder el comentario de @ mango).
fuente
Generalmente, no, no defina funciones dentro de funciones.
A menos que tenga una muy buena razón. Lo cual no tienes.
Por qué no?
lambda
expresión en su lugar .¿Cuál es una buena razón para definir funciones dentro de funciones?
Cuando lo que realmente quieres es un cierre dingdang .
fuente
De hecho, está bien declarar una función dentro de otra. Esto es especialmente útil para crear decoradores.
Sin embargo, como regla general, si la función es compleja (más de 10 líneas), podría ser una mejor idea declararla en el nivel del módulo.
fuente
Encontré esta pregunta porque quería plantear una pregunta por qué hay un impacto en el rendimiento si uno usa funciones anidadas. Ejecuté pruebas para las siguientes funciones usando Python 3.2.5 en un portátil con Windows con un procesador Intel Core i5-2530M Quad Core 2.5 GHz
Medí las siguientes 20 veces, también para square1, square2 y square5:
y obtuve los siguientes resultados
square0
no tiene función anidada,square1
tiene una función anidada,square2
tiene dos funciones anidadas ysquare5
tiene cinco funciones anidadas. Las funciones anidadas solo se declaran pero no se llaman.Entonces, si ha definido 5 funciones anidadas en una función que no llama, entonces el tiempo de ejecución de la función es el doble de la función sin una función anidada. Creo que debería ser cauteloso al usar funciones anidadas.
El archivo Python para toda la prueba que genera esta salida se puede encontrar en ideone .
fuente
Es solo un principio sobre las API de exposición.
Usando python, es una buena idea evitar la exposición API en el espacio exterior (módulo o clase), la función es un buen lugar de encapsulación.
Podría ser una buena idea cuando te aseguras
Aunque, el abuso de esta técnica puede causar problemas e implica un defecto de diseño.
Solo desde mi exp. Quizás malinterprete su pregunta.
fuente
Entonces, al final, se trata en gran medida de cuán inteligente es o no la implementación de Python, particularmente en el caso de que la función interna no sea un cierre, sino simplemente un ayudante necesario en función.
En un diseño limpio y comprensible, tener funciones solo donde se necesitan y no estar expuestas en otro lugar es un buen diseño, ya sea que estén integradas en un módulo, una clase como método o dentro de otra función o método. Cuando se hace bien, realmente mejoran la claridad del código.
Y cuando la función interna es un cierre que también puede ayudar con bastante claridad, incluso si esa función no se devuelve de la función de contención para su uso en otro lugar.
Por lo tanto, diría que generalmente los usa, pero tenga en cuenta el posible impacto en el rendimiento cuando realmente le preocupa el rendimiento y solo elimínelos si realiza un perfil real que muestre que es mejor eliminarlos.
No haga una optimización prematura simplemente usando "funciones internas MALAS" en todo el código de Python que escriba. Por favor.
fuente
Está perfectamente bien hacerlo de esa manera, pero a menos que necesite usar un cierre o devolver la función, probablemente lo pondría en el nivel del módulo. Me imagino que en el segundo ejemplo de código quieres decir:
de lo contrario, some_data será la función.
Tenerlo en el nivel del módulo permitirá que otras funciones usen method_b () y si está usando algo como Sphinx (y autodoc) para la documentación, también le permitirá documentar method_b.
También es posible que desee considerar simplemente poner la funcionalidad en dos métodos en una clase si está haciendo algo que pueda ser representable por un objeto. Esto también contiene lógica si eso es todo lo que estás buscando.
fuente
Haz algo como:
si tuvieras que correr
some_function()
, entonces correríasome_other_function()
y devolvería 42.EDITAR: Originalmente dije que no deberías definir una función dentro de otra, pero se señaló que a veces es práctico hacerlo.
fuente
Puede usarlo para evitar definir variables globales. Esto le brinda una alternativa para otros diseños. 3 diseños que presentan una solución a un problema.
A) Usar funciones sin globals
B) Usar funciones con globales
C) Usar funciones dentro de otra función
La solución C) permite utilizar variables en el ámbito de la función externa sin tener la necesidad de declararlas en la función interna. Puede ser útil en algunas situaciones.
fuente
Función en la función python
fuente