我有两个可迭代的对象,希望将它们链接起来,即将它们连接起来。具体来说,对象是可迭代的,返回一个迭代器,并且可以重复。这两个迭代的串联应该是一个迭代,每次从输入中获取两个迭代,并返回串联的迭代。我对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
,只是这个想法有两个参数可能更可读(