考虑以下交互式示例
>>> l=imap(str,xrange(1,4))
>>> list(l)
['1', '2', '3']
>>> list(l)
[]
有没有人知道是否已经在某处实现了一个版本的imap(和其他itertools函数),这样第二次执行列表(l)就会得到与第一次相同的结果。而且我不想要常规地图,因为如果使用更大的范围,在内存中构建整个输出可能会浪费内存。
我想要一些基本上像
这样的东西class cmap:
def __init__(self, function, *iterators):
self._function = function
self._iterators = iterators
def __iter__(self):
return itertools.imap(self._function, *self._iterators)
def __len__(self):
return min( map(len, self._iterators) )
但如果有人已经这样做,那么对所有itertools手动执行此操作将是浪费时间。
PS。 你认为容器比迭代器更禅,因为对于像
这样的迭代器for i in iterator:
do something
在明确需要删除元素的容器时隐式清空迭代器。
答案 0 :(得分:7)
您不必为每种类型的容器构建此类对象。基本上,您有以下内容:
mkimap = lambda: imap(str,xrange(1,4))
list(mkimap())
list(mkimap())
现在你需要一个很好的包装对象来防止“丑陋”的函数调用。这可以这样工作:
class MultiIter(object):
def __init__(self, f, *a, **k):
if a or k:
self.create = lambda: f(*a, **k)
else: # optimize
self.create = f
def __iter__(self):
return self.create()
l = MultiIter(lambda: imap(str, xrange(1,4)))
# or
l = MultiIter(imap, str, xrange(1,4))
# or even
@MultiIter
def l():
return imap(str, xrange(1,4))
# and then
print list(l)
print list(l)
(未经测试,希望它有效,但你应该明白这一点)
对于你的第二个问题:迭代器和容器都有它们的用途。你应该采取最符合你需要的东西。
答案 1 :(得分:1)
您可能正在寻找itertools.tee()
答案 2 :(得分:-1)
迭代器是我最喜欢的主题;)
from itertools import imap
class imap2(object):
def __init__(self, f, *args):
self.g = imap(f,*args)
self.lst = []
self.done = False
def __iter__(self):
while True:
try: # try to get something from g
x = next(self.g)
except StopIteration:
if self.done:
# give the old values
for x in self.lst:
yield x
else:
# g was consumed for the first time
self.done = True
return
else:
self.lst.append(x)
yield x
l=imap2(str,xrange(1,4))
print list(l)
print list(l)