무한 생성기에 대한 표현이 있습니까?


119

무한한 요소를 생성 할 수있는 간단한 생성기 표현식이 있습니까?

이것은 순전히 이론적 인 질문입니다. 여기에 "실용적인"대답이 필요 없습니다. :)


예를 들어, 유한 제너레이터를 만드는 것은 쉽습니다.

my_gen = (0 for i in xrange(42))

그러나 무한한 것을 만들려면 내 네임 스페이스를 가짜 함수로 "오염"시켜야합니다.

def _my_gen():
    while True:
        yield 0
my_gen = _my_gen()

별도의 파일에서 작업하고 import나중에 -ing하는 것은 중요하지 않습니다.


나는 또한 그것이 itertools.repeat정확히 이것을 한다는 것을 압니다 . 그것없이 한 줄짜리 솔루션이 있는지 궁금합니다.


9
실제로 네임 스페이스를 오염시킬 필요는 없습니다 . 함수의 이름을 지정한 my_gen다음 my_gen = my_gen().
6502

2
del _my_gen두 가지를 혼동하지 않으려면 사용할 수도 있습니다
John La Rooy 2011

답변:


133
for x in iter(int, 1): pass
  • 2 인수 iter= 0 인수 호출 가능 + 센티넬 값
  • int() 항상 반환 0

따라서 iter(int, 1)무한 반복자입니다. 이 특정 테마에는 분명히 수많은 변형이 있습니다 (특히 lambda믹스에 추가 한 경우). 특정 메모의 한 가지 변형은 iter(f, object()), 새로 생성 된 객체를 센티넬 값으로 사용하면 첫 번째 인수로 사용되는 콜 러블에 관계없이 거의 무한 반복자를 보장하기 때문입니다.


3
우리가 자주 잊어 버리는 iter속성 을 사용 하는 매우 흥미로운 방법 int입니다.
Senthil Kumaran 2011

3
당신은 시뮬레이션이 마법 레시피를 사용할 수 있습니다 itertools.count:count = lambda start=0, step=1: (start + i*step for i, _ in enumerate(iter(int, 1)))
Coffee_Table

1
여기서 무슨 일이 일어나고 있는지 설명하기 위해 : iter두 개의 인수를 사용 하여 -function을 호출 하면 평소와는 약간 다르게 동작합니다 iter(callable, sentinel) -> iterator.. 인수 1 은 값을 반환 할 때까지callable 반복기의 모든 반복에 대해 호출됩니다 . 그러나, 항상 반환 , 우리는 호출 할 수있는 효과이 의지의 무한 목록 생성 1. 영원히 결코 도달 의sentinelint()0int()0
Olsgaard

217

itertools 세 가지 무한 생성기를 제공합니다.

나는 표준 라이브러리의 다른 어떤 것도 모른다.


한 줄짜리를 요청했기 때문에 :

__import__("itertools").count()

18
Re : repeat (x, times = ∞)- 궁금한 사람을위한 상징 은 없습니다 -인수를 생략하면 영원히 반복됩니다
Mr_and_Mrs_D

(ncoghlan의 답변이 OP의 질문을 직접 해결하는 동안) 이것이 더 일반적으로 적용 가능하기 때문에 찬성되었습니다.
Huw Walters

이것은 iter(int, 1)주문 보다 훨씬 더 읽기 쉽습니다. Too bad itertoolsendlessly()유일한 목적이 이것을 하는 방법을 가지고 있지 않습니다 . itertools.count()모두 읽을 수있는 것도 아닙니다.
BallpointBen

19

iter ()의 센티넬과 항상 다른 상수를 반환하는 콜 러블을 반복 할 수 있습니다.

g1=iter(lambda:0, 1)

8
나는 이것을 좋아하고 싫어한다 ... 나는 그것이 내가 원하는 것을 너무 적은 캐릭터로 성취한다는 것을 좋아하지만, 아무도 그것을 보지 않고 그것이 무엇을 해야하는지 알지 않는 방법을 싫어한다.
ArtOfWarfare

1
iter(여기서는 여분의 센티넬이있는) 구문과 구문 lambda(여기서는 전달 된 매개 변수없이 그냥 return 0)을 아는 것만 으로도 미워할 수있는 유일한 장소는 수수께끼 g1입니다.
Sławomir Lenart

트윗 담아 가기 부끄럽게 작아서 1g을 분출했습니다.
user237419

8

OS는 무한 생성기로 사용할 수있는 무언가를 제공 할 수 있습니다. 예 : Linux에서

for i in (0 for x in open('/dev/urandom')):
    print i

분명히 이것은 효율적이지 않습니다.

for i in __import__('itertools').repeat(0)
    print i

11
/ dev / urandom 솔루션 \n은 때때로 나타나는 s에 달려 있습니다 . :)
hugomg 2011

5

클래스 / 함수 / 생성자로 정의 된 다른 무한 반복기를 내부적으로 사용하지 않는 없음 (-expression이 아님,을 사용하는 함수 yield). 생성기 표현식은 항상 반복 가능한 anoter에서 가져오고 항목을 필터링하고 매핑하는 것 외에는 아무것도하지 않습니다. 만에 무한한 것과 유한 한 항목에서 갈 수 없어 map하고 filter, 당신이 필요로 while(또는 for우리는 사용 할 수 없습니다 정확히 무엇 인 종료되지 않는 for및 유한 반복자).

퀴즈 : PEP 3142 는 표면적으로 비슷하지만 자세히 살펴보면 여전히 for조항이 필요한 것 같습니다 (그래서 아니오 (0 while True)). 즉, itertools.takewhile.


내가 생각했듯이 ... 남용 할 수있는 즉시 사용할 수있는 무한 생성기가 없다는 것을 확신 할 수 있습니까? (슬프게도 xrange (0,1, -1)가 작동하지 않습니다 ...)
hugomg

2
@missingno : from itertools import repeat, count, cycle아마도 대부분의 사람들에게 "즉시 사용 가능"한 것으로 간주됩니다.
ncoghlan 2011

1
죄송합니다 iter. 2 인수에 대해 잊어 버렸습니다 . 무한 반복자는 내장으로 실제로 사용할 수있는 - 내 대답 : 참조
ncoghlan

5

매우 추하고 미친 짓이지만 (매우 웃기지 만) 몇 가지 트릭을 사용하여 표현식에서 고유 한 반복기를 만들 수 있습니다 (필요에 따라 네임 스페이스를 "오염"하지 않고).

{ 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,), {}))() } 

당신은 분명히 LISP를 사랑합니다
Faissaloo

1
@Faissaloo Indeed ... 내가 쓴 오래된 페이지에서 더 미친 표현을 찾을 수 있습니다 : baruchel.github.io/python/2018/06/20/…
Thomas Baruchel

2

예를 들어 다음과 같은 데코레이터를 사용할 수 있습니다.

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

나는 그 추악한 것을 제거하는 것이 더 개선 될 수 있다고 생각한다 (). 그러나 만들 수있는 시퀀스의 복잡성에 따라 다릅니다. 일반적으로 시퀀스를 함수를 사용하여 표현할 수 있다면 생성자의 모든 복잡성과 구문 설탕이 데코레이터 또는 데코레이터와 같은 함수 안에 숨겨 질 수 있습니다.


9
OP는 oneliner를 요구하고 3 중 중첩 def및 클로저가 있는 10 줄 데코레이터를 제공 합니까? ;)

2
@delnan 음, 데코레이터를 한 번 정의하면 하나의 라이너를 가질 수 있습니까? 내가 이해했듯이 목적은 각 추가 무한 생성기를 한 줄로 구현하는 것입니다. 그리고 이것이 여기에 제시된 것입니다. 당신은 가질 (2^x)수 있습니다 (x). 당신이 그것을 약간 개선한다면 피보나치, 등등.
julx

내 질문에 대답하지 않지만 어떻게 그 모든 푹신한 클로저를 좋아하지 않을 수 있습니까? BTW, 나는 당신 seq이 코드를 제거 하고 직접 들여 쓰기 하여 여분의 괄호를 제거 할 수 있다고 확신합니다wrap
hugomg
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.