Есть ли выражение для бесконечного генератора?
Есть ли прямое выражение генератора, которое может давать бесконечные элементы?
Это чисто теоретический вопрос. Нет необходимости в "практическом" ответе здесь:)
Например, легко сделать конечную генерацию:
my_gen = (0 for i in xrange(42))
Однако, чтобы сделать бесконечный, мне нужно "загрязнить" мое пространство имен фальшивой функцией:
def _my_gen():
while True:
yield 0
my_gen = _my_gen()
Выполнение действий в отдельном файле и import
-ing позже не учитывается.
Я также знаю, что itertools.repeat
делает именно это. Мне любопытно, есть ли однострочное решение без этого.
Ответы
Ответ 1
for x in iter(int, 1): pass
- Два аргумента
iter
= аргумент с нулевым аргументом, вызываемый + отправитель
-
int()
всегда возвращает 0
Следовательно, iter(int, 1)
- бесконечный итератор. Очевидно, что существует огромное количество вариаций в этой теме (особенно после добавления lambda
в микс). Одним из вариантов конкретного примечания является iter(f, object())
, поскольку используется только что созданный объект, поскольку значение дозорного элемента почти гарантирует бесконечный итератор независимо от вызываемого, используемого в качестве первого аргумента.
Ответ 2
itertools
содержит три бесконечных генератора:
-
count(start=0, step=1)
: 0, 1, 2, 3, 4,...
-
cycle(p)
: p [0], p [1],..., p [-1], p [0],...
-
repeat(x, times=∞)
: x, x, x, x,...
Я не знаю других в стандартной библиотеке.
Поскольку вы попросили один-лайнер:
__import__("itertools").count()
Ответ 3
вы можете перебирать вызываемый вызов, возвращающий константу, всегда отличающуюся от iter() sentinel
g1=iter(lambda:0,1)
Ответ 4
Ваша ОС может предоставить что-то, что может использоваться как бесконечный генератор. Например, на linux
for i in (0 for x in open('/dev/urandom')):
print i
очевидно, это не так эффективно, как
for i in __import__('itertools').repeat(0)
print i
Ответ 5
Нет, который не использует внутренний бесконечный итератор, определяемый как класс/функция/генератор (не-выражение, функция с yield
). Выражение генератора всегда извлекается из anoter iterable и ничего не делает, кроме фильтрации и отображения его элементов. Вы не можете перейти от конечных элементов к бесконечным с помощью map
и filter
, вам нужно while
(или for
, которое не завершается, что именно то, что мы не можем использовать только for
и конечные итераторы).
Общая информация: PEP 3142 внешне похожа, но при ближайшем рассмотрении кажется, что для этого по-прежнему требуется предложение for
(поэтому no (0 while True)
для вас), т.е. предоставляет только ярлык для itertools.takewhile
.
Ответ 6
Возможно, вы могли бы использовать такие декораторы, как это, например:
def generator(first):
def wrap(func):
def seq():
x = first
while True:
yield x
x = func(x)
return seq
return wrap
Использование (1):
@generator(0)
def blah(x):
return x + 1
for i in blah():
print i
Использование (2)
for i in generator(0)(lambda x: x + 1)():
print i
Я думаю, что его можно было бы улучшить, чтобы избавиться от этих уродливых ()
. Однако это зависит от сложности последовательности, которую вы хотите создать. Вообще говоря, если ваша последовательность может быть выражена с помощью функций, то вся сложность и синтаксический сахар генераторов могут быть скрыты внутри декоратора или подобной декоратору функции.
Ответ 7
Довольно уродливый и сумасшедший (очень забавный, однако), но вы можете создать свой собственный итератор из выражения, используя некоторые трюки (без необходимости "загрязнять" ваше пространство имен по мере необходимости):
{ print("Hello world") for _ in
(lambda o: setattr(o, '__iter__', lambda x:x)
or setattr(o, '__next__', lambda x:True)
or o)
(type("EvilIterator", (object,), {}))() }
Ответ 8
def iter_cycle(iterator):
saved = []
for iterable in iterator:
yield iterable
saved.append(iterable)
while saved:
for element in saved:
yield element
a = iter_cycle(iter([1,2,3]))
next (a) → 1 следующий (а) → 2 next (a) → 3
next (a) → 1
(как уже упоминалось, благодаря документации python https://docs.python.org/2/library/itertools.html#itertools.cycle)