如何将可迭代内容链接起来



我有两个可迭代的对象,希望将它们链接起来,即将它们连接起来。具体来说,对象是可迭代的,返回一个迭代器,并且可以重复。这两个迭代的串联应该是一个迭代,每次从输入中获取两个迭代,并返回串联的迭代。我对Python还是相当陌生的,发现它非常微妙和困难——不像";"容易";每个人告诉这是一种语言。但我本以为有一种简单的方法来完成这项特殊的任务。来自itertools的注释链不起作用:

from itertools import chain
def i():
n = 0
while n < 2:
yield n
n = n+1
def j():
m = 0
while m < 3:
yield m
m = m+1
print("iterating i")        
for x in i():
print(x)

print("iterating i again")   
for x in i():
print(x)

k = chain(i(),j())
print("iterating k")    
for x in k:
print(x)

print("iterating k again")   
for y in k:
print(y)
print("but it's empty :(")

给出

iterating i
0
1
iterating i again
0
1
iterating k
0
1
0
1
2
iterating k again
but it's empty :(

在这里,chain似乎是在给出迭代器的迭代器上操作的,但我想将两个给出可迭代的可迭代对象链接起来。

对初步意见的回应:

我不认为这是一个关于生成器的问题:我只是用生成器来说明。

有些人说iterable已经没有东西了。但据我所知,这是不对的:iterable总是可以生成新的迭代器。您可以看到i((可以重复。一个特定的迭代器已经用完。这个问题是关于迭代器和可迭代的之间的区别。

最后,我当然可以将数据保存在一个列表中,并在该列表上随意迭代多次。但我想让你想象一下,2和3太大了,这是不切实际的。

提前感谢:(

这就是生成器的工作方式。用莱曼的话说,你用过一次之后,它就空了。这个想法不是使用新的内存来存储东西,而是在运行时创建东西

当你执行k = chain(i(),j())时,你会创建生成器对象k,在第一个for x in k循环中,你会清空它。现在,当你试图在for y in k循环中循环相同的k时,迭代器k中没有什么可迭代的了

在第一个for x in i()循环中,调用i()并在那里创建一个新的生成器进行循环。在for y in i()中再次执行此操作,您将在一个新生成器上循环;不是你以前使用的旧

如果你想多次使用k,你可以创建一个列表,而不是生成器

k = list(chain(i(), j()))

编辑:如果不需要列表,只需使用for x in chain(i(), j())for y in chain(i(), j()),而不是for .. in k即可。这将在每个for循环中创建一个新的生成器对象。k = chain(i(), j())只创建一个生成器,而您正试图使用它两次

正如我所说,Python是微妙的。而且似乎真的很难解释我想要什么,更不用说去做了!

我现在有一些代码,可以做我想做的事。它不是特别漂亮。我已经把发电机上的东西拿走了,因为这似乎是在转移注意力。如果这真的是Python中最简单的方法,那么它就是我问题的答案。但有人可能知道一个更简单的方法。

from itertools import chain
# make iterators without using generators
class iterthing:
def __init__( self , n ):
self._max = n
def __iter__( self ):
return iter(range(self._max))

i = iterthing(2)
j = iterthing(3)
print("iterating i")        
for x in i:
print(x)
print("iterating j")        
for x in j:
print(x)

print("iterating i again")   
for x in i:
print(x)
# join two iterables
class metachain:
def __init__( self, i , j ):
self._first = i
self._second = j
def __iter__( self ):
return chain( iter(self._first), iter(self._second) )

k = metachain(i,j)
print("iterating k")    
for x in k:
print(x)

print("iterating k again")   
for y in k:
print(y)
print("this time it repeats as required with no lists stored in memory")

您可以通过定义自己的期望函数的链来实现一些魔术:

def mychain(f1,f2):
return itertools.chain(f1(),f2())

然后使用functools.partial()创建您的k:

k=functools.partial(mychain,i,j)
for x in k():
print(x);
print("again")
for x in k():
print(x)

(当然,你可以把它做成*args,只是这个想法有两个参数可能更可读(

最新更新