development

왜 파이썬은 for 및 while 루프 후에 'else'를 사용합니까?

big-blog 2020. 2. 21. 22:31
반응형

왜 파이썬은 for 및 while 루프 후에 'else'를 사용합니까?


이 구문이 어떻게 작동하는지 이해합니다.

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

    if i == 9:
        print("Too big - I'm giving up!")
        break;
else:
    print("Completed successfully")

그러나 왜 else키워드가 키워드로 사용 되는지 이해하지 못합니다 . for블록이 완료되지 않은 경우에만 문제의 코드가 실행된다는 것을 암시하기 때문입니다. 내가 어떻게 생각하든 내 두뇌는 for성명서에서 else블록으로 완벽하게 진행될 수 없습니다 . 나에게 continue또는 continuewith더 이해가 될 것입니다 (그리고 나는 그것을 읽도록 훈련하려고합니다).

파이썬 코더 가이 구문을 머리에서 읽는 방법이 궁금합니다 (또는 원하는 경우 큰 소리로). 아마도 그러한 코드 블록을 더 쉽게 해독 할 수있는 것을 놓치고 있습니까?


노련한 파이썬 코더조차도 이상한 구성입니다. for-loops와 함께 사용하면 기본적으로 "반복 가능한 항목을 찾으십시오. 에서처럼 :

found_obj = None
for obj in objects:
    if obj.key == search_key:
        found_obj = obj
        break
else:
    print('No object found.')

그러나이 구문을 볼 때마다 더 나은 대안은 검색을 함수로 캡슐화하는 것입니다.

def find_obj(search_key):
    for obj in objects:
        if obj.key == search_key:
            return obj

또는 목록 이해력을 사용하십시오.

matching_objs = [o for o in objects if o.key == search_key]
if matching_objs:
    print('Found {}'.format(matching_objs[0]))
else:
    print('No object found.')

의미 적으로 다른 두 버전과 동일하지는 않지만 전체 목록을 반복하는지 여부와 상관없이 성능이 중요하지 않은 코드에서는 충분히 잘 작동합니다. 다른 사람들은 동의하지 않을 수도 있지만, 개인적으로 프로덕션 코드에서 for-else 또는 while-else 블록을 사용하지 않는 것이 좋습니다.

[Python-ideas] for ... else 스레드 요약 참조


일반적인 구성은 무언가를 찾을 때까지 루프를 실행 한 다음 루프를 벗어나는 것입니다. 문제는 루프에서 벗어나거나 루프가 종료되면 어떤 사건이 발생했는지 확인해야한다는 것입니다. 한 가지 방법은 플래그 또는 저장 변수를 작성하여 루프가 어떻게 종료되었는지 확인하기 위해 두 번째 테스트를 수행하는 것입니다.

예를 들어 목록을 검색하고 플래그 항목을 찾을 때까지 각 항목을 처리 한 다음 처리를 중지해야한다고 가정합니다. 플래그 항목이 없으면 예외를 발생시켜야합니다.

파이썬을 사용하면 for... else당신이 구성

for i in mylist:
    if i == theflag:
        break
    process(i)
else:
    raise ValueError("List argument missing terminal flag.")

이 구문 설탕을 사용하지 않는 방법과 이것을 비교하십시오.

flagfound = False
for i in mylist:
    if i == theflag:
        flagfound = True
        break
    process(i)

if not flagfound:
    raise ValueError("List argument missing terminal flag.")

첫 번째 경우에는 raisefor 루프와 밀접하게 바인딩됩니다. 두 번째로 바인딩이 강력하지 않고 유지 관리 중에 오류가 발생할 수 있습니다.


Raymond Hettinger는 Transforming Code를 Beautiful, Idiomatic Python으로 변환 하는 훌륭한 프리젠 테이션을 통해 작문 의 역사를 간단히 설명합니다 for ... else. 관련 섹션은 15:50에서 시작하여 약 3 분 동안 계속되는 "루프에서 다중 종료점 구별" 입니다. 요점은 다음과 같습니다.

  • for ... else구조는 특정 GOTO사용 사례를 대체하기 위해 Donald Knuth에 의해 고안되었습니다 .
  • 재사용 else키워드 만든 의미가 있기 때문 "해당 시간, 크 누스 사용, 사람들이 알고있는 것을있어, 모든 [ for문]은 내장했다 ifGOTO아래, 그들은 예상 else;"
  • 뒤늦은 통찰력은 "휴식 없음"(또는 아마도 "휴식 없음")으로 불리어야하는데 혼란스럽지 않습니다. *

질문이 "왜이 키워드를 바꾸지 않습니까?" 그러면 Cat Plus Plus가 가장 정확한 답을 제공했을 것입니다 .이 시점에서 기존 코드를 구현하기에는 너무 파괴적입니다. 그러나 당신이 정말로 묻는 질문이 else처음부터 재사용 된 이유라면 , 아마도 당시에는 좋은 생각처럼 보였습니다.

개인적으로, 나는 루프 내부에 속하는 것으로 한눈에 오해 할 수있는 # no break곳이라면 어디에서나 인라인 주석 을 작성 하는 것을 좋아합니다 else. 합리적으로 명확하고 간결합니다. 이 옵션은 Bjorn 이 그의 대답 끝에 연결 한 요약 에서 간단히 언급 합니다 .

완성도를 높이기 위해 구문을 약간 변경하면이 구문을 원하는 프로그래머는 지금 구문을 사용할 수 있습니다.

for item in sequence:
    process(item)
else:  # no break
    suite

* 비디오의 해당 부분에 대한 보너스 인용 : "람다 makefunction 을 호출 한 것처럼 아무도 '람다는 무엇을합니까?'


언어에 새로운 키워드를 도입하고 싶지 않았기 때문입니다. 각각은 식별자를 훔치고 이전 버전과의 호환성 문제를 유발하므로 일반적으로 최후의 수단입니다.


간단하게하기 위해 그렇게 생각할 수 있습니다.

  • 루프 에서 break명령 이 발생하면 부품이 호출되지 않습니다.forelse
  • 루프 에서 break명령이 발생하지 않으면 부품이 호출됩니다.forelse

다시 말해, for 루프 반복이로 "깨지지 않은" break경우 else부품이 호출됩니다.


for / else가 무엇을했는지 '가져올'수있는 가장 쉬운 방법은 더 중요하게는 언제 사용해야하는지 break break가 어디로 가는지에 집중하는 것이 었습니다. For / else 구문은 단일 블록입니다. 브레이크는 블록 밖으로 점프하므로 else 절을 ​​'오버'합니다. else 절의 내용이 단순히 for 절 다음에 오면 절대로 건너 뛰지 않으므로 if에 넣으면 동등한 논리를 제공해야합니다. 이것은 이전에 언급되었지만,이 말에서는 그다지 알려지지 않았으므로 다른 사람에게 도움이 될 수 있습니다. 다음 코드 조각을 실행하십시오. 나는 명확성을 위해 '휴식 없음'이라는 의견에 진심으로 찬성한다.

for a in range(3):
    print(a)
    if a==4: # change value to force break or not
        break
else: #no break  +10 for whoever thought of this decoration
    print('for completed OK')

print('statement after for loop')

나는 문서의 큰 설명이 있다고 생각 다른 사람을 , 계속

[...] 루프가 목록의 소진을 통해 종료 될 때 (with) 또는 조건이 false가되는 동안 (with가있는 경우) 실행되지만 break 문으로 루프가 종료 될 때는 실행되지 않습니다. "

출처 : Python 2 Docs : 제어 흐름에 대한 자습서


나는 그것을 다음과 같이 읽었다.

루프를 실행하는 조건에 여전히 있다면, 다른 일을하십시오.


기술 부분에 대한 답변이 많았으므로이 의견은 재활용 키워드 를 생성 하는 혼란 과 관련 있습니다.

파이썬은 매우 훌륭한 프로그래밍 언어 이기 때문에 키워드의 오용은 더 악명 높습니다. else키워드는 의사 결정 트리 흐름의 일부를 완벽하게 설명합니다. "이 작업을 수행 할 수없는 경우에는 그렇게하십시오" 그것은 우리 자신의 언어로 암시 됩니다.

대신에이 키워드를 사용 while하고 for진술하는 것은 혼란을 만듭니다. 그 이유는 프로그래머로서의 우리의 경력은 그 else진술이 의사 결정 트리 내에 있다는 것을 가르쳐주었습니다 . 그것의 논리적 범위 , 래퍼 조건부 경로를 따라갑니다. 한편, 루프 문은 무언가를 달성하려는 비유적인 명시 적 목표를 가지고 있습니다. 프로세스의 지속적인 반복 후에 목표가 달성됩니다.

if / else 따라야 할 경로를 나타냅니다 . "목표"가 완료 될 때까지 루프 는 경로를 따릅니다 .

문제는 else조건에서 마지막 옵션을 명확하게 정의하는 단어입니다. 단어 의미Python과 Human Language가 공유 합니다. 그러나 Human Language의 else 단어는 무언가가 완료된 후 누군가 또는 무언가가 취할 행동을 나타내는 데 사용되지 않습니다. 그것은 그것을 완료하는 과정에서 경우에 사용되며, 문제는 (더 같이 상승 휴식 문).

결국 키워드는 파이썬으로 유지됩니다. 모든 프로그래머가 니모닉 장치와 같은 사용법을 이해하기 위해 스토리를 만들려고 할 때 실수 였고 분명했습니다. 키워드 대신 키워드를 선택하면 좋았습니다 then. 이 키워드는 반복적 인 흐름, 루프 후의 보수 에 완벽하게 부합한다고 생각합니다 .

그리고 : 그것은 그 어떤 아이가 장난감을 조립의 모든 단계를 수행 한 후에도 가지고 상황과 유사 THEN 어떤 아빠?


나는 " iterable가 완전히 소진되고 실행이 끝나고 나서 다음 명령문으로 진행하려고 할 for때 else 절이 실행될 것 "과 같이 읽었습니다 . 따라서 반복이에 의해 끊어지면 break실행되지 않습니다.


나는 '엘리 프가 아닌 [조건을 깨는 조건]'과 같다는 데 동의합니다.

나는 이것이 오래된 스레드라는 것을 알고 있지만 지금 같은 질문을 조사하고 있으며 아무도 내가이 질문에 대한 답을 내가 이해하는 방식으로 포착했는지 확신 할 수 없습니다.

나에게있어 elsein For... else이나 While... else문장 을 "읽는"방법은 세 가지 가 있는데, 모두 동등하다 :

  1. else == if the loop completes normally (without a break or error)
  2. else == if the loop does not encounter a break
  3. else == else not (condition raising break) (아마 그런 조건이 있거나 루프가 없을 것입니다)

따라서 본질적으로 루프의 "else"는 실제로 "elif ..."입니다. 여기서 '...'는 (1) 중단이 없으며, 이는 (2) NOT [break (들)를 일으키는 조건]과 같습니다.

핵심은 else'브레이크'가 없으면 의미가 없다는 것이므로 다음을 for...else포함합니다.

for:
    do stuff
    conditional break # implied by else
else not break:
    do more stuff

따라서 for...else루프 의 필수 요소는 다음과 같으며 일반 영어로 읽을 수 있습니다.

for:
    do stuff
    condition:
        break
else: # read as "else not break" or "else not condition"
    do more stuff

다른 포스터가 말했듯이 일반적으로 루프가 찾고있는 것을 찾을 수있을 때 중단이 발생하므로 else:"대상 항목을 찾지 못하면 어떻게해야합니까?"가됩니다.

예외 처리, 중단 및 for 루프를 모두 함께 사용할 수도 있습니다.

for x in range(0,3):
    print("x: {}".format(x))
    if x == 2:
        try:
            raise AssertionError("ASSERTION ERROR: x is {}".format(x))
        except:
            print(AssertionError("ASSERTION ERROR: x is {}".format(x)))
            break
else:
    print("X loop complete without error")

결과

x: 0
x: 1
x: 2
ASSERTION ERROR: x is 2
----------
# loop not completed (hit break), so else didn't run

중단이 발생한 간단한 예입니다.

for y in range(0,3):
    print("y: {}".format(y))
    if y == 2: # will be executed
        print("BREAK: y is {}\n----------".format(y))
        break
else: # not executed because break is hit
    print("y_loop completed without break----------\n")

결과

y: 0
y: 1
y: 2
BREAK: y is 2
----------
# loop not completed (hit break), so else didn't run

중단이없고 중단을 발생시키는 조건이없고 오류가 발생하지 않는 간단한 예입니다.

for z in range(0,3):
     print("z: {}".format(z))
     if z == 4: # will not be executed
         print("BREAK: z is {}\n".format(y))
         break
     if z == 4: # will not be executed
         raise AssertionError("ASSERTION ERROR: x is {}".format(x))
else:
     print("z_loop complete without break or error\n----------\n")

결과

z: 0
z: 1
z: 2
z_loop complete without break or error
----------

else키워드는 여기 혼란, 그리고 많은 사람들이 지적 밖으로, 같은 것을 가지고 할 수있다 nobreak, notbreak더 적합하다.

이해하기 위해서는 for ... else ...논리적으로 비교 try...except...else하지 if...else..., 파이썬 프로그래머의 대부분은 다음 코드에 익숙 :

try:
    do_something()
except:
    print("Error happened.") # The try block threw an exception
else:
    print("Everything is find.") # The try block does things just find.

마찬가지로, break특별한 종류의 것으로 생각하십시오 Exception:

for x in iterable:
    do_something(x)
except break:
    pass # Implied by Python's loop semantics
else:
    print('no break encountered')  # No break statement was encountered

차이점은 python내포 except break되어 있으며 작성할 수 없으므로 다음과 같이됩니다.

for x in iterable:
    do_something(x)
else:
    print('no break encountered')  # No break statement was encountered

그렇습니다. 나는이 비교가 어렵고 번거로울 수 있다는 것을 알고 있지만 혼란을 분명히합니다.


루프가 끊어지지 않으면 else명령문 블록의 코드 가 실행됩니다 for.

for x in xrange(1,5):
    if x == 5:
        print 'find 5'
        break
else:
    print 'can not find 5!'
#can not find 5!

로부터 문서 : 휴식 및 말씀, 그리고 루프에 대한 다른 조항을 계속

루프 문은 else 절을 ​​가질 수 있습니다. 루프가 목록의 소진을 통해 종료 될 때 (with) 또는 조건이 false가 될 때 (with가있는 경우) 실행되지만 break 문으로 루프가 종료되는 경우에는 실행되지 않습니다. 이는 소수를 검색하는 다음 루프로 예시됩니다.

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(예, 이것은 올바른 코드입니다. 자세히 살펴보면 else 절은 if 문이 아니라 for 루프에 속합니다.)

루프와 함께 사용될 때 else 절은 if 문의 것보다 try 문의 else 절과 더 공통적입니다. try 문의 else 절은 예외가 발생하지 않을 때 실행되고 루프의 else 절은 중단이 없을 ​​때 실행됩니다. . try 문 및 예외에 대한 자세한 내용은 예외 처리를 참조하십시오.

C에서 빌린 continue 문은 다음 루프 반복으로 계속됩니다.

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9

위에서 언급 한 다른 사람을 보지 못한 방법에 대해 생각해보십시오.

먼저, for-loops는 기본적으로 while-loop 주위의 구문 설탕이라는 것을 기억하십시오. 예를 들어 루프

for item in sequence:
    do_something(item)

다음과 같이 (약) 다시 쓸 수 있습니다

item = None
while sequence.hasnext():
    item = sequence.next()
    do_something(item)

둘째, while 루프는 기본적으로 if 블록 만 반복된다는 것을 기억하십시오! "이 조건이 참이면 본문을 실행 한 다음 다시 와서 다시 확인하십시오."로 while 루프를 읽을 수 있습니다.

따라서 while / else는 완벽하게 이해됩니다. if / else와 완전히 동일한 구조이며 조건을 한 번만 확인하는 대신 조건이 false가 될 때까지 반복 기능이 추가되었습니다.

그리고 for / else도 완벽하게 이해됩니다. 모든 for-loops는 while-loops의 상단에있는 구문 설탕이기 때문에 기본 while-loop의 암시 적 조건이 무엇인지 알아 내야합니다. 조건이 False가됩니다.


else루프에서 수행되지 않은 다른 것 또는 다른 것에서 와 같이 생각할 수 있습니다.


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

    if i == 2:
        print("Too big - I'm giving up!")
        break;
else:
    print("Completed successfully")

여기서 "그렇지 않다"는 아주 단순합니다.

1, " for clause완료된 경우 "

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

    if i == 2:
        print("Too big - I'm giving up!")
        break;
if "for clause is completed":
    print("Completed successfully")

"for clause is completed"와 같은 긴 문장을 작성해야하므로 "else"를 소개합니다.

else 여기에 자연의 if가 있습니다.

그러나, 어떻습니까? for clause is not run at all

In [331]: for i in range(0):
     ...:     print(i)
     ...: 
     ...:     if i == 9:
     ...:         print("Too big - I'm giving up!")
     ...:         break
     ...: else:
     ...:     print("Completed successfully")
     ...:     
Completed successfully

그래서 그것은 완전히 논리 조합입니다 :

if "for clause is completed" or "not run at all":
     do else stuff

또는 이런 식으로 넣으십시오.

if "for clause is not partially run":
    do else stuff

또는 이런 식으로 :

if "for clause not encounter a break":
    do else stuff

검색 외에 또 다른 관용적 사용 사례가 있습니다. 예를 들어, 원격 서버에서 포트가 열려 있고 시간 초과와 같은 조건이 충족 될 때까지 기다렸다 고 가정 해 봅시다. 그런 다음 다음 while...else과 같은 구문을 활용할 수 있습니다.

import socket
import time

sock = socket.socket()
timeout = time.time() + 15
while time.time() < timeout:
    if sock.connect_ex(('127.0.0.1', 80)) is 0:
        print('Port is open now!')
        break
    print('Still waiting...')
else:
    raise TimeoutError()

훌륭한 답변은 다음과 같습니다.

  • 이것은 역사를 설명하고
  • 이것은 당신의 번역 / 이해를 쉽게하기 위해 올바른 인용을 제공합니다.

내 노트는 도널드 크 누스 (Donald Knuth)가 한 번 말했듯이 (미안하지만 참조가 불가능합니다) while-else가 if-else와 구별 할 수없는 구조, 즉 (Python에서)라는 구성에서 나온 것입니다.

x = 2
while x > 3:
    print("foo")
    break
else:
    print("boo")

다음과 같은 흐름 (낮은 레벨 차이 제외)이 있습니다.

x = 2
if x > 3:
    print("foo")
else:
    print("boo")

요점은 if-else가 블록 break의 끝에 암시적인 while-else의 구문 설탕으로 간주 될 수 있다는 것입니다 if. 반대의 의미는, 그 while루프에 확장 if때문에, (그냥 반복 것 / 조건 검사를 루프) 더 일반적인 if종종 전에 진행됩니다 while. 그러나 이것은 조건이 거짓 일 때 마다else 블록 인 동안 실행되는 것을 의미하기 때문에 사실이 아닙니다 .

이해를 돕기 위해 다음과 같이 생각하십시오.

않고 break, return조건이있는 경우 등, 루프 말단은 더 이상 진정한 이러한 경우에 else블록도 한번 실행하지 않습니다. Python의 경우 forC 스타일 for루프 (조건 포함)를 고려하거나로 변환해야합니다 while.

다른 메모 :

조기 break, return등 내부 루프는 조건이 사실과 다시 그것을 확인하기 위해 다시 오지 않을 것 동안 실행이 루프 밖으로 뛰어 때문에 조건이 거짓이 될 불가능합니다.


방금 다시 이해하려고 노력했습니다. 나는 다음이 도움이된다는 것을 알았다!

•가 아닌 루프 내부 else와 짝을 이루는 것으로 생각하십시오. 조건이 충족되면 루프를 끊으십시오. 그렇지 않으면 루프 가 여러 개와 짝을 이루는 것을 제외하고이 작업을 수행하십시오 ! s가 전혀 만족 되지 않으면 을 수행하십시오 . • 여러 개도 실제로 - 로 간주 될 수 있습니다 !ifforelseif
ifelse
ififelif


파이썬은 else for for 및 while 루프를 사용하므로 루프에 아무것도 적용되지 않으면 다른 일이 발생합니다. 예를 들면 다음과 같습니다.

test = 3
while test == 4:
     print("Hello")
else:
     print("Hi")

출력은 'Hi'를 반복해서 반복합니다 (정확한 경우).


나는 (경우) 다른 B에서와 구조를 고려하고, 대한 (있는 경우) -else이다 특별한 경우 - 다른 사람이 , . 다른 이해하는 데 도움이 될 수 있습니다 .

A와 B는 최대 한 번 실행되며 if-else 구조와 동일합니다.

for (if)는 if 조건을 충족시키기 위해 루프를 수행하는 특수 if로 간주 될 수 있습니다. 한때 경우 조건이 충족 될 때, A와 휴식 ; 그렇지 않으면 B.

참고 URL : https://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops



반응형