2017-12-22 6 views
0

python3에서 다음 코드가 숫자 0, 1, 2, 3, 4를 인쇄하는 이유는 무엇입니까?python3에서 목록 이해력과 생성자를 사용하여 인쇄

[print(i) for i in range(5)] 

하지만 당신은 발전기와 같은 일을 할 경우는 아무것도하지 않습니다

당신은 발전기와 같은 결과를 얻을 수있는 유일한 방법처럼 반복하는
(print(i) for i in range(5)) 

입니다 이 :

z = (print(i) for i in range(5)) 
for i in z: 
    i 
+0

[질문] (질문 답변 : https://stackoverflow.com/questions/47789/generator-expressions-vs-list-comprehension) –

+0

@GarbageCollector 답장을 보내 주셔서 감사합니다. 나는이 질문을 보았고 목록과 발전기의 차이점을 알고 있다고 말해야한다. 필자는 목록이나 생성기에 요소를 추가하는 대신 함수를 호출하려고합니다. 첫 번째 함수가 실제로 함수를 호출하게하는 배경에서 어떤 일이 일어나고 있는지 알고 싶습니다. –

+1

'print' 대신에'f'라는 함수를 실행하는 데 오랜 시간이 걸린다 고 상상해보십시오. 우리가 발전기를 사용하는 이유는 게으른 평가를 활용하는 것입니다. 여기서 우리는 우리가 필요로하지 않는 계산을하지 않습니다. 우리가 'z = (f (i) for i (range (5))'에 쓸 때), 우리는 발전기 이해력을 설정하고 있지만 실제로 그것이 설명하는 계산을 수행하지는 않습니다. 게으른 평가와'def' 구문을 사용하여 파이썬에서 직접 생성기를 작성하는 방법에 대해 좀 더 연구를 해보길 권합니다. –

답변

2

생성기 표현식에서 반환 한 개체와 같은 생성기는 지연 반복기입니다. 요청한 값을 제공하는 데 필요한만큼의 코드 만 실행합니다. 생성기에서 반복하지 않으면 값을 요구하지 않으므로 코드가 실행되지 않으므로 아무 것도 인쇄되지 않습니다.

당신은에 next를 호출하여 반복자에서 개별 값을 요청할 수 있습니다

gen = (print(i) for i in range(5)) 

x = next(gen) # causes 0 to be printed 
y = next(gen) # causes 1 to be printed 

next에 대한 첫 번째 호출은 발전기에서 첫 번째 값을 요청, 그래서이 range에서 첫 번째 값 print를 호출 . next에 대한 두 번째 호출은 range의 두 번째 값을 인쇄합니다. xy 모두 None으로 지정됩니다. 이는 print이 반환하므로 생성기에서 산출 한 값입니다.

당신이 for 루프에서 발전기를 넣어 (또는 인수를 통해 반복 list 같은 함수에 전달), 전체 발전기가 소비 될 경우, 당신이 배의 무리 그것에 next를 호출하는 경우 등이있다. next을 수동으로 계속 호출하면 결국 StopIteration 예외가 발생합니다. 반복기가 반환 할 값이 더 이상 없다는 신호입니다.

발전기와 달리 목록 이해력이 게으르지 않기 때문에 시도한 목록 이해력에 동일한 동작이 없었습니다.모든 코드를 즉시 실행하고 가져온 모든 값에서 목록을 만듭니다. 귀하의 목록을 이해하면 None 개의 값으로 가득 찬 목록이 작성되므로 (print의 결과이므로) 목록이 채워지면서 모든 번호가 인쇄됩니다.

코드 버전이 매우 Pythonic이 아닙니다. 일반적으로 부작용 (예 : print 값)에 대해서만 생성기 식 또는 목록 이해를 사용해서는 안됩니다. 산출 된 값을 염려 할 때 (또는리스트에 넣을 때) 사용하십시오. 당신은 단지 숫자의 범위를 인쇄 할 경우에, 다만 직접 범위에 for 루프를 사용하고, 루프의 본문에 print 전화 :

for i in range(5): 
    print(i) 

이 있습니까 허용 지능형리스트 또는 코드 생성기의 표현이다 부작용은 계산되는 값이 유용 할 때까지 가능합니다. 첫 번째 줄에 지능형리스트가 주로 사용되는

results = [client.send(message) for client in clients] # client.send may return an error code 
for result in results: # process the results after all the messages were sent 
    if result is not None: # no error means success 
     print("client.send error:", result) # report failures, but keep going 

: 당신이 신뢰할 수없는 네트워크를 통해 여러 클라이언트에 메시지를 보내려는 경우 예를 들어, 당신은 이런 식으로 뭔가를보고 몇 가지 코드를 사용할 수 있습니다 그것의 부작용 (메시지를 보내는 것)은 무엇이 발생했는지 알 수 있기 때문에 반환 값의 목록도 유용합니다.

+0

기본적인 오타가 수정되었습니다. :) –

+0

@MadPhysicist : 감사합니다! – Blckknght

2

당신이

(print(i) for i in range(5)) 
와 발전기 객체를 생성하기 때문입니다

목록이 아닙니다.

list(print(i) for i in range(5)) 

으로 변경하면 첫 번째 진술과 동일하게 작동합니다.

생성기는 특수한 유형의 반복기입니다. 자세한 내용은 Python 설명서 here을 참조하십시오.

(print(i) for i in range(5))의 괄호 사이에있는 코드는 반복기가 반복 될 때까지 실제로 인쇄 기능을 호출하지 않을 때 생성 된 패턴을 '반복 실행'하는 방법을 생성기에 알려줍니다. 목록은 목록 이해 때문에 인쇄 기능을 호출합니다. [print(i) for i in range(5)] 또는 list(print(i) for i in range(5))를 사용하기 때문에 지능형리스트에

for i in range(5): 
    print i 

에 해당합니다. 그래서 실제로 print 함수를 호출하고 있습니다. 목록 이해에 대한 자세한 내용은 this 웹 사이트를 확인하십시오.

+0

하지만 왜 이런 일이 발생합니까? 왜 제네레이터가 프린트 기능을 호출하지 않고 목록이 작동하지 않습니까? –

+1

생성자는 'iterator'객체를 생성하기 때문에 print 함수를 호출하지 않습니다. 내 편집을 확인하십시오. – B3W

+0

@ B3W. 생성기는 반복을 요청할 때까지 아무 작업도 수행하지 않습니다. 그것은 게으른 프로세싱의 성격과 발전기의 모든 목적입니다. –

관련 문제