Itertools для контейнеров - PullRequest
       3

Itertools для контейнеров

9 голосов
/ 15 августа 2011

Рассмотрим следующий интерактивный пример

>>> 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, если кто-то уже сделал это.

пс. Как вы думаете, контейнеры - это больше дзен, чем итераторы, поскольку для итератора что-то вроде

for i in iterator:
    do something

неявно очищает итератор, в то время как контейнер вам явно нужен для удаления элементов.

Ответы [ 3 ]

7 голосов
/ 15 августа 2011

Вам не нужно создавать такой объект для каждого типа контейнера. По сути, у вас есть следующее:

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 голос
/ 15 августа 2011

Возможно, вы ищете itertools.tee ()

0 голосов
/ 15 августа 2011

Итераторы - моя любимая тема;)

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...