[PyVigo] [Py-ES] Don’t Use Recursion In Python Any More,Python Closure — A Pythonic technique you must know

Chema Cortes pych3m4 en gmail.com
Mie Ene 6 04:19:34 CET 2021


El mar, 5 ene 2021 a las 16:19, Jesus Cea (<jcea en jcea.es>) escribió:

> On 4/1/21 11:18, Chema Cortes wrote:
> > La recursividad en python es muy limitada. Pero lo que viene a descubrir
> > es algo que se podría haber hecho mejor con generadores. En cuanto al
> > otro uso, sería una aplicación parcial de argumentos (functools.partial).
> >
> > Aún así, hay algoritmos recursivos que no son tan fácilmente
> > transcribibles en iterables.
>
> Más allá del uso chorras para convertir una función concreta de
> recursiva a iterativa, para mí lo interesante del artículo es el uso de
> "closures" para generar funciones personalizadas que se llevan su estado
> consigo. No todo necesita el coste de crear clases e instancias
> explícitas, no todo se puede solucionar con generadores y
> "functools.partial()" no proporciona estado mutable.
>
> El uso de "closures" explícitos me parece algo que vale la pena añadir a
> la caja de herramientas, siempre vigilando que no existe una forma más
> elegante de hacer algo concreto.
>
>
Aunque suene bien que las funciones mantengan su propio estado, nunca es
aconsejable que las funciones tengan efectos colaterales (violación de
la transparencia
referencial <https://en.wikipedia.org/wiki/Referential_transparency>).

Las clausuras son importantes y están en el fondo de muchos recursos como
pueden ser los *decoradores*. Pero es siempre posible crear un generador (
Iterable) en lugar de una función con clausura (Callable). La diferencia es
que los generadores están *protocolizados*,  con opciones para poner fin a
la iteración (StopIteration), para inyectar datos a la clausura (método
.send()) o para destruir el generador (GeneratorExit). También se pueden
usar en gran parte de la librería estándar, con las funciones de itertools
como las más potentes.

Por comparar, la función de fibonacci como generador:

from itertools import islice

def fib():
    a, b = 1, 1
    while True:
        yield a
        a, b = b, a+b

def fib_generator(n):
    return next(islice(fib(), n-1, None))


Si se compara, es casi el doble de rápida que la que viene en el artículo,
fib_closure.

Saludos.


-- 
Hyperreals *R  "Quarks, bits y otras criaturas infinitesimales":
https://blog.ch3m4.org
Buscador Python Hispano: http://busca.ch3m4.org
<https://blog.ch3m4.org/pages/busqueda-python-es/>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <https://lists.es.python.org/pipermail/vigo/attachments/20210106/3b7beb38/attachment.htm>


Más información sobre la lista de distribución Vigo