Когда вы используете генератор понимания, вы можете использовать итерацию только один раз. Например.
>>> 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
, не будет проблемой.