2017-12-13 5 views
2

오늘 ''에서 '평가 시간 차이'아래에있는 잡아 당김을 발견하고 힘든 시간을 보내고 있습니다.발전기의 평가 시간 불일치를 해결하는 방법

내 문제에 대한 간략한 시연, 나는 n[2..5]에서가는 모든 n 일 번호를 건너 무한 발전기합니다

from itertools import count 

skip_lists = [] 
for idx in range(2, 5): 
    # skip every 2nd, 3rd, 4th.. number 
    skip_lists.append(x for x in count() if (x % idx) != 0) 

# print first 10 numbers of every skip_list 
for skip_list in skip_lists: 
    for _, num in zip(range(10), skip_list): 
     print("{}, ".format(num), end="") 
    print() 

예상 출력 :

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 
1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 
1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 

실제 출력 :

1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 
1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 
1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 
다시

from itertools import count 

skip_lists = [] 
for idx in range(2, 5): 
    # bind the skip distance 
    skip_lists.append([idx]) 
    # same as in the first try, but use bound value instead of 'idx' 
    skip_lists[-1].append(x for x in count() if (x % skip_lists[-1][0]) != 0) 

# print first 10 numbers of every skip_list 
for skip_list in (entry[1] for entry in skip_lists): 
    for _, num in zip(range(10), skip_list): 
     print("{}, ".format(num), end="") 
    print() 

:하지만

1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 
1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 
1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 
내가 그 훌륭한 기능을 기억하면 088,243,210

, 나는 skip_list의 일부가 될 것입니다 일정에 if 절 변수를 결합하여 "해결"을 시도

실제 솔루션 외에도 해킹이 작동하지 않는 이유를 알고 싶습니다.

답변

3

idx = 4 최신 iteratee 값이 모듈 범위에있는 지점 인 발전기에서 반복을 시작할 때까지 (발전기가 느리게 평가되는) 최대의 값이 검색되지 않습니다.

idx에 각 추가 생성기를 상태 저장하려면 함수에 idx을 전달하고 각 생성기 평가 시간에 함수 범위에서 값을 읽습니다. 이것은 생성자 표현식의 반복 가능한 소스가 gen에서 평가된다는 사실을 이용합니다. 경험치의 작성 시간이되도록 기능 루프의 각 반복에서 불러 idx 함수 범위에서 얻어 저장 안전하게이다 : 겐에서 생성 식의 반복 가능한 소스 평가

from itertools import count 

skip_lists = [] 

def skip_count(skip): 
    return (x for x in count() if (x % skip) != 0) 


for idx in range(2, 5): 
    # skip every 2nd, 3rd, 4th.. number 
    skip_lists.append(skip_count(idx)) 

그림. 특급의 창조 다음 제외 실제로 세대 특급의 작성시에 평가되지 않은 필터에서 수행되기 때문에

>>> (i for i in 5) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'int' object is not iterable 

귀하의 경우는 조금 복잡합니다 :

>>> (i for i in range(2) if i in 5) 
<generator object <genexpr> at 0x109a0da50> 

더 많은 이유 왜 루프 및 필터는 모두 idx을 저장하는 범위로 이동해야합니다. 필터 만이 아닙니다.다른 주에


, 당신은 당신이 슬라이스 발전기 표현의 인쇄하는 데 사용하는 대신 비효율적 인 논리 itertools.islice을 사용할 수 있습니다 : 내 코드는 지금 작동

from itertools import islice 

for skip_list in skip_lists: 
    for num in islice(skip_list, 10): 
     print("{}, ".format(num), end="") 
    print() 
+0

멋진 대답을 =) 그러나 나는 skip_lists.append ([idx])에'idx'를 저장하는 것이 왜'idx' 대신에 접근하는지 이해하지 못한다. 그 값은 마지막 반복으로 바뀌지 않습니다.'print (skip_list)'는 결국 두 번째 예제에서 [[2, ], [3, ], [4, ]]을 산출합니다. – Arne

+0

생성자 표현식의 코드 객체는 평가할 때 처음에 루프가 완료된 후'idx' 이름을 읽습니다. 그 루프 이후에'idx'를 출력하는 것과 비슷합니다. 그 시점에서'idx'라는 이름은 int 4를 참조합니다. –

+0

그것은 끔찍한 것입니다. skip_lists.append ([lambda x idx : x])조차도 로컬 범위 참조를 만드는 데는 효과가 없습니다. 이 문제를 해결하는 방법을 알려 주셔서 감사합니다. – Arne

관련 문제