我试图通过使用itertools.count()压缩zip来将functools.partial与itertools.count一起使用:
g = functools.partial(zip, itertools.count())
当使用诸如“ abc”,“ ABC”之类的输入调用g时,我注意到itertools.count()神秘地“跳跃”。
我认为我应该得到与直接将zip与itertools.count()使用相同的结果?喜欢:
>>> x=itertools.count();
>>> list(zip("abc",x))
[('a', 0), ('b', 1), ('c', 2)]
>>> list(zip("ABC",x))
[('A', 3), ('B', 4), ('C', 5)]
但是,相反,我得到以下内容-注意g的第二次调用的起始索引是4而不是3:
>>> g = functools.partial(zip, itertools.count())
>>> list(g("abc"))
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> list(g("ABC"))
[(4, 'A'), (5, 'B'), (6, 'C')]
答案 0 :(得分:5)
请注意,如果您的原始代码以与更改后的代码相同的顺序使用参数,则会得到相同的结果:
>>> x = itertools.count()
>>> list(zip(x, "abc"))
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> list(zip(x, "ABC"))
[(4, 'A'), (5, 'B'), (6, 'C')]
zip()
首先尝试其第一个参数,然后尝试其第二个参数,然后再尝试其第三个参数……并在其中一个参数用尽时停止。
在上面的拼写中,"abc"
用尽之后,它返回第一个参数,并从3
中获得x
。但是它的第二个参数已经用尽,因此zip()
停止了,3
默默地丢失了。
然后继续前进到第二个zip()
,并从4
中获取x
。
partial()
确实与它无关。
答案 1 :(得分:4)
很容易看出为什么将itertools.count()
封装在一个函数中:
def count():
c = itertools.count()
while True:
v = next(c)
print('yielding', v)
yield v
g = functools.partial(zip, count())
list(g("abc"))
输出为
yielding 0
yielding 1
yielding 2
yielding 3
[(0, 'a'), (1, 'b'), (2, 'c')]
您将看到zip
将评估count()
中的下一个参数(这样会产生一个额外的值3
),然后才意识到第二个可迭代项中没有其他内容。
作为练习,反转参数,您会发现计算结果有所不同。