libreria example español python python-3.x itertools

example - ¿Cuál es el propósito en itertools.repeat de Python?



product() python (6)

Como se mencionó anteriormente, funciona bien con zip :

Otro ejemplo:

from itertools import repeat fruits = [''apples'', ''oranges'', ''bananas''] # Initialize inventory to zero for each fruit type. inventory = dict( zip(fruits, repeat(0)) )

Resultado:

{''apples'': 0, ''oranges'': 0, ''bananas'': 0}

Para hacer esto sin repetición, tendría que involucrar a len(fruits) .

Cada vez que puedo pensar en la clase itertools.repeat() Python, se me ocurre otra solución igualmente aceptable (posiblemente más) para lograr el mismo efecto. Por ejemplo:

>>> (i for i in itertools.repeat(''example'', 5)) (''example'', ''example'', ''example'', ''example'', ''example'') >>> (''example'') * 5 (''example'', ''example'', ''example'', ''example'', ''example'') >>> map(str.upper, itertools.repeat(''example'', 5)) [''EXAMPLE'', ''EXAMPLE'', ''EXAMPLE'', ''EXAMPLE'', ''EXAMPLE''] >>> [''example''.upper()] * 5 [''EXAMPLE'', ''EXAMPLE'', ''EXAMPLE'', ''EXAMPLE'', ''EXAMPLE'']

¿Hay algún caso en el que sería la solución más adecuada? De ser así, ¿bajo qué circunstancias?


El propósito principal de itertools.repeat es proporcionar un flujo de valores constantes para usar con map o zip :

>>> list(map(pow, range(10), repeat(2))) # list of squares [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

El propósito secundario es que proporciona una forma muy rápida de realizar un bucle de un número fijo de veces como esta:

for _ in itertools.repeat(None, 10000): do_something()

Esto es más rápido que:

for i in range(10000): do_something().

El primero gana porque todo lo que necesita hacer es actualizar el recuento de referencia para el objeto Ninguno existente. Este último pierde porque el rango () o xrange () necesita fabricar 10,000 objetos enteros distintos.

Tenga en cuenta que el propio Guido utiliza esa técnica de bucle rápido en el módulo timeit() . Consulte la fuente en https://hg.python.org/cpython/file/2.7/Lib/timeit.py#l195 :

if itertools: it = itertools.repeat(None, number) else: it = [None] * number gcold = gc.isenabled() gc.disable() try: timing = self.inner(it, self.timer)


Es un iterador. Gran pista aquí: está en el módulo de itertools. De la documentación que has vinculado a:

itertools.repeat (objeto [, veces]) Crea un iterador que devuelve el objeto una y otra vez. Se ejecuta indefinidamente a menos que se especifique el argumento times.

Así que nunca tendrás todas esas cosas en la memoria. Un ejemplo donde quieras usarlo podría ser

n = 25 t = 0 for x in itertools.repeat(4): if t > n: print t else: t += x

ya que esto te permitirá un número arbitrario de 4 s, o lo que necesites, una lista infinita de.


La función itertools.repeat es perezosa; solo utiliza la memoria requerida para un elemento. Por otro lado, los modismos (a) * n y [a] * n crean n copias del objeto en la memoria. Para cinco elementos, el lenguaje de multiplicación es probablemente mejor, pero es posible que note un problema de recursos si tuviera que repetir algo, por ejemplo, un millón de veces.

Aún así, es difícil imaginar muchos usos estáticos para itertools.repeat . Sin embargo, el hecho de que itertools.repeat sea ​​una función le permite utilizarla en muchas aplicaciones funcionales. Por ejemplo, es posible que tenga alguna función de func biblioteca que funcione en una entrada iterable. A veces, es posible que tenga listas preconstruidas de varios elementos. Otras veces, es posible que desee operar en una lista uniforme. Si la lista es grande, itertools.repeat te ahorrará memoria.

Finalmente, repeat hace posible el llamado "álgebra de iteradores" descrito en la documentación de itertools . Incluso el itertools módulo itertools utiliza la función de repeat . Por ejemplo, el siguiente código se proporciona como una implementación equivalente de itertools.izip_longest (aunque probablemente el código real esté escrito en C). Tenga en cuenta el uso de repeat siete líneas desde la parte inferior:

class ZipExhausted(Exception): pass def izip_longest(*args, **kwds): # izip_longest(''ABCD'', ''xy'', fillvalue=''-'') --> Ax By C- D- fillvalue = kwds.get(''fillvalue'') counter = [len(args) - 1] def sentinel(): if not counter[0]: raise ZipExhausted counter[0] -= 1 yield fillvalue fillers = repeat(fillvalue) iterators = [chain(it, sentinel(), fillers) for it in args] try: while iterators: yield tuple(map(next, iterators)) except ZipExhausted: pass


Su ejemplo de foo * 5 parece superficialmente similar a itertools.repeat(foo, 5) , pero en realidad es bastante diferente.

Si escribe foo * 100000 , el intérprete debe crear 100,000 copias de foo antes de que pueda darle una respuesta. Por lo tanto, es una operación muy costosa y hostil para la memoria.

Pero si escribe itertools.repeat(foo, 100000) , el intérprete puede devolver un iterador que cumple la misma función y no necesita calcular un resultado hasta que lo necesite, por ejemplo, usándolo en una función que desee Para saber cada resultado en la secuencia.

Esa es la principal ventaja de los iteradores: pueden diferir el cálculo de una parte (o todas) de una lista hasta que realmente necesite la respuesta.


Suelo usar repetición junto con cadena y ciclo. Aquí hay un ejemplo:

from itertools import chain,repeat,cycle fruits = [''apples'', ''oranges'', ''bananas'', ''pineapples'',''grapes'',"berries"] inventory = list(zip(fruits, chain(repeat(10,2),cycle(range(1,3))))) print inventory

Pone las 2 primeras frutas como valor 10, luego alterna los valores 1 y 2 para las frutas restantes.