Синтаксис для многократного повторения? - PullRequest
0 голосов
/ 16 января 2019

Когда вы используете генератор понимания, вы можете использовать итерацию только один раз. Например.

>>> g = (i for i in xrange(10))
>>> min(g)
0
>>> max(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: max() arg is an empty sequence

Что немного раздражает, если учесть, что это работает не так, как списки.

Вы можете сделать g = lambda (): (i for i in xrange(10)), чтобы сделать его многоразовым, но тогда вам нужно будет сделать g () вместо g (РЕДАКТИРОВАТЬ: проблема с этим не в том, что g () слишком длинный для ввода, но это если функция ожидает итерацию, вы не можете сказать ей делать g () вместо g.__iter__()). Вы также можете сделать

class gObject(object):
    def __iter__(self): return (i for i in xrange(10))

g = gObject()

но это значительно дольше, чем набирать g = (i for i in xrange(10)). Есть ли более короткий синтаксис, чем gObject для выполнения этой задачи?

Примечания:

  • Мы можем предположить, что итерируемое не будет потреблять элементы из других постоянных итерируемых. Например, если бы я сделал z = iter(xrange(10)), я бы не пытался определить g = (i for i in z), поскольку это могло бы работать только один раз (без клонирования z).
  • g больше не будет итератором. Скорее, теперь это будет повторяемым. Я в порядке с этим. Действительно, это как раз то, что нужно.
  • Это должно работать для бесконечных итераций. Например, понимание списка не будет работать, поскольку оно работает только в конечных случаях.
  • Мы можем предположить, что любые затраты на инициализацию дешевы, поэтому повторный запуск кода, определяющего g, не будет проблемой.

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Нет, нет более краткого синтаксиса, потому что то, что вы запрашиваете, является очень нишевым случаем, а не тем, для которого Python решает оказать особую поддержку.

0 голосов
/ 16 января 2019

Я не полностью слежу за комментариями, но itertools.tee может дать мне несколько итераций:

In [518]: g1,g2,g3 = itertools.tee((i for i in range(10)), 3)
In [519]: min(g1), max(g2)
Out[519]: (0, 9)
In [520]: a = 0
In [521]: while a<10:
     ...:     a += next(g3)      # simulate an infinite sequence
     ...:     
In [522]: a
Out[522]: 10
In [523]: list(g3)
Out[523]: [5, 6, 7, 8, 9]

или без распаковки:

def foo(g):
    a=0
    while a<12:
        a += next(g)
    return (a, list(g))

In [525]: alist = itertools.tee((i for i in range(10)),3)
     ...: flist = [min, max, foo]
     ...: for f,a in zip(flist, alist):
     ...:     print(f(a))
0
9
(15, [6, 7, 8, 9])

(используется Py3)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...