Homero Xing
Quiero cambiar el siguiente código.
for directory, dirs, files in os.walk(directory_1):
do_something()
for directory, dirs, files in os.walk(directory_2):
do_something()
a este código:
for directory, dirs, files in os.walk(directory_1) + os.walk(directory_2):
do_something()
me sale el error:
tipos de operandos no admitidos para +: ‘generador’ y ‘generador’
¿Cómo unir dos generadores en Python?
Felipe
itertools.chain()
Deberías hacerlo. Toma múltiples iterables y rendimientos de cada uno, aproximadamente equivalente a:
def chain(*iterables):
for it in iterables:
for element in it:
yield element
Ejemplo de uso:
from itertools import chain
g = (c for c in 'ABC') # Dummy generator, just for example
c = chain(g, 'DEF') # Chain the generator and a string
for item in c:
print(item)
Producción:
A
B
C
D
E
F
-
Se debe tener en cuenta que el valor de retorno de
itertools.chain()
no devuelve untypes.GeneratorType
instancia. En caso de que el tipo exacto sea crucial.– Riga
16 sep 2019 a las 13:45
-
Ver @andrew-pate anser para itertools.chain.from_iterable() referencia para devolver una instancia de types.GeneratorType.
– gkedge
9 de septiembre de 2020 a las 13:13
-
itertools.chain() daría todos los elementos en un directorio y luego cambiaría al otro directorio. Ahora, ¿cómo elegimos los primeros elementos de ambos directorios y realizamos algunas operaciones, y luego cambiamos al siguiente par y así sucesivamente? Cualquier idea sera apreciada.
– yash
9 de febrero de 2021 a las 11:07
-
@yash Iterar sobre esos directorios manualmente usando la función incorporada próximo.
– Jeyekomon
16 de febrero de 2021 a las 8:57
-
@yash te puede gustar Código Postal. Hace precisamente eso, selecciona los valores primero, segundo, etc. y los pone en tuplas.
– Randelung
18 mayo 2021 a las 21:00
Un ejemplo de código:
from itertools import chain
def generator1():
for item in 'abcdef':
yield item
def generator2():
for item in '123456':
yield item
generator3 = chain(generator1(), generator2())
for item in generator3:
print item
-
¿Por qué no agregar este ejemplo a los ya existentes, altamente votados?
itertools.chain()
¿respuesta?– Jean-François Corbett
15 de octubre de 2018 a las 7:13
-
Um. Porque le hubiera costado 850 rep. El tipo tiene 851. Tú sí, cesio.
– Tatarizar
14 de diciembre de 2020 a las 10:38
-
@ Jean-FrançoisCorbett, la persona que escribió la respuesta “ya existente” podría haber hecho eso realmente … ¿de acuerdo? 🙂
– Oso de hielo
27 de diciembre de 2020 a las 10:37
-
Se ha agregado un ejemplo a la respuesta principal, lo que hace que esto sea redundante.
– wjandrea
17 de julio de 2022 a las 0:52
uduse
En Python (3.5 o superior) puedes hacer:
def concat(a, b):
yield from a
yield from b
-
Mucho pitónico.
– ramazán polat
28 oct 2018 a las 18:18
-
Mas general:
def chain(*iterables): for iterable in iterables: yield from iterable
(Pon eldef
yfor
en líneas separadas cuando lo ejecuta).– wjandrea
12 de abril de 2019 a las 15:29
-
es todo de a cedido ante cualquier cosa de b se ceden o se alternan?
– oficial de problemas – nf Monica
10 de diciembre de 2019 a las 16:22
-
@problemofficer Sí. Solo
a
se verifica hasta que se obtiene todo de él, incluso sib
no es un iterador. ÉlTypeError
porb
no ser un iterador aparecerá más adelante.– GeeTransit
4 de enero de 2020 a las 16:10
-
@Karolius Oh, está bien, veo lo que estás diciendo. Parece que cometiste un error tipográfico, lo que me confundió:
def chain(iterable)
debiera serdef chain(iterables)
. (También,x for x in
es redundante). De todos modos, ya hay una herramienta en stdlib que hace eso:itertools.chain.from_iterable
. Y más allá del rendimiento, si tuvieras un infinito iterable de iterables, es no sería posible para usar el desembalaje.– wjandrea
17 de julio de 2022 a las 1:22
usuario1767754
Ejemplo sencillo:
from itertools import chain
x = iter([1,2,3]) #Create Generator Object (listiterator)
y = iter([3,4,5]) #another one
result = chain(x, y) #Chained x and y
paté andrés
Con itertools.chain.from_iterable puedes hacer cosas como:
def genny(start):
for x in range(start, start+3):
yield x
y = [1, 2]
ab = [o for o in itertools.chain.from_iterable(genny(x) for x in y)]
print(ab)
-
Está utilizando una comprensión de lista innecesaria. También está utilizando una expresión de generador innecesaria en
genny
cuando ya devuelve un generador.list(itertools.chain.from_iterable(genny(x)))
es mucho más conciso.– Cormán
25 mayo 2020 a las 20:31
-
La comprensión de la lista fue una manera fácil de crear los dos generadores, según la pregunta. Tal vez mi respuesta es un poco complicada en ese sentido.
– andrew paté
26 mayo 2020 a las 22:29
-
Supongo que la razón por la que agregué esta respuesta a las existentes fue para ayudar a aquellos que tienen muchos generadores con los que lidiar.
– andrew paté
26 mayo 2020 a las 22:41
-
No es una manera fácil, hay muchas maneras más fáciles. El uso de expresiones de generador en un generador existente reducirá el rendimiento y el
list
constructor es mucho más legible que la lista de comprensión. Su método es mucho más ilegible en esos aspectos.– Cormán
27 de mayo de 2020 a las 0:48
-
Corman, estoy de acuerdo en que su constructor de listas es más legible. Sin embargo, sería bueno ver sus ‘muchas formas más fáciles’… Creo que el comentario anterior de wjandrea parece hacer lo mismo que itertools.chain.from_iterable, sería bueno competir con ellos y ver quién es el más rápido.
– andrew paté
27 de mayo de 2020 a las 9:25
Roberto Siemer
Aquí está usando un generador de expresión con anidado for
s:
range_a = range(3)
range_b = range(5)
result = (item
for one_range in (range_a, range_b)
for item in one_range)
assert list(result) == [0, 1, 2, 0, 1, 2, 3, 4]
Él for ... in ...
se evalúan de izquierda a derecha. El identificador después for
establece una nueva variable. Tiempo one_range
en uso en el siguiente for ... in ...
la item
del segundo se usa en la expresión de asignación „final” de la cual solo hay una (al principio).
-
Está utilizando una comprensión de lista innecesaria. También está utilizando una expresión de generador innecesaria en
genny
cuando ya devuelve un generador.list(itertools.chain.from_iterable(genny(x)))
es mucho más conciso.– Cormán
25 mayo 2020 a las 20:31
-
La comprensión de la lista fue una manera fácil de crear los dos generadores, según la pregunta. Tal vez mi respuesta es un poco complicada en ese sentido.
– andrew paté
26 mayo 2020 a las 22:29
-
Supongo que la razón por la que agregué esta respuesta a las existentes fue para ayudar a aquellos que tienen muchos generadores con los que lidiar.
– andrew paté
26 mayo 2020 a las 22:41
-
No es una manera fácil, hay muchas maneras más fáciles. El uso de expresiones de generador en un generador existente reducirá el rendimiento y el
list
constructor es mucho más legible que la lista de comprensión. Su método es mucho más ilegible en esos aspectos.– Cormán
27 de mayo de 2020 a las 0:48
-
Corman, estoy de acuerdo en que su constructor de listas es más legible. Sin embargo, sería bueno ver sus ‘muchas formas más fáciles’… Creo que el comentario anterior de wjandrea parece hacer lo mismo que itertools.chain.from_iterable, sería bueno competir con ellos y ver quién es el más rápido.
– andrew paté
27 de mayo de 2020 a las 9:25
andrea
Actualización de 2020: funciona tanto en Python 3 como en Python 2
import itertools
iterA = range(10,15)
iterB = range(15,20)
iterC = range(20,25)
primera opción
for i in itertools.chain(iterA, iterB, iterC):
print(i)
# 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
opción alternativa, introducida en python 2.6
for i in itertools.chain.from_iterable( [iterA, iterB, iterC] ):
print(i)
# 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
itertools.cadena() es el básico.
itertools.chain.from_iterable() es útil si tiene un iterable de iterables. Por ejemplo, una lista de archivos por subdirectorio como [ ["src/server.py", "src/readme.txt"], ["test/test.py"] ]
.
-
Python 2 finalizó el 1 de enero de 2020, así que me sorprende que lo menciones
– wjandrea
17 de julio de 2022 a las 1:31