Mệnh đề khác trên Python while statement


321

Tôi đã nhận thấy đoạn mã sau là hợp pháp trong Python. Câu hỏi của tôi là tại sao? Có một lý do cụ thể?

n = 5
while n != 0:
    print n
    n -= 1
else:
    print "what the..."

5
@detly: Đó là vì hầu hết mọi người tránh cấu trúc này. :) Tôi tin rằng Guido đã đề cập trong quá trình Py3k rằng, ít nhất, việc lựa chọn từ elsenày cho việc sử dụng này là một ý tưởng tồi tệ đáng kinh ngạc, và họ sẽ không làm gì thêm nữa.
Hiệp sĩ Nicholas

5
@Nicholas Knight - vâng, hấp dẫn mặc dù vậy, nó có lẽ là thứ mà chỉ tôi hiểu từ cái nhìn đầu tiên. Bất kỳ người nghèo nào khác cũng sẽ phải đi và xem thông số ngôn ngữ, hoặc quay ngược thời gian và gửi câu hỏi tại đây trên Sta- heeeeey ...
gièm pha

8
Ý tưởng đằng sau việc chọn 'other' là cấu trúc này được cho là thường được sử dụng cùng với một 'if X: break' bên trong vòng lặp while. Vì mệnh đề 'other' được thực thi nếu chúng ta không thoát ra khỏi vòng lặp, nó tạo thành một loại 'khác' thành 'if'.
Jonathan Hartley

12
Họ nên đổi tên nó after:.
naught101

Câu trả lời:


388

Các elsekhoản chỉ được thực hiện khi bạn whileđiều kiện trở thành sai. Nếu bạn breakra khỏi vòng lặp, hoặc nếu một ngoại lệ được nêu ra, nó sẽ không được thực thi.

Một cách để nghĩ về nó là một cấu trúc if / other liên quan đến điều kiện:

if condition:
    handle_true()
else:
    handle_false()

tương tự như cấu trúc lặp:

while condition:
    handle_true()
else:
    # condition is false now, handle and go on with the rest of the program
    handle_false()

Một ví dụ có thể nằm dọc theo dòng:

while value < threshold:
    if not process_acceptable_value(value):
        # something went wrong, exit the loop; don't pass go, don't collect 200
        break
    value = update(value)
else:
    # value >= threshold; pass go, collect 200
    handle_threshold_reached()

42
"Mệnh đề khác chỉ được thực thi khi điều kiện while của bạn trở thành sai." Từ ngữ ở đây ngụ ý rằng trạng thái trong khi của bạn chuyển từ trạng thái đúng sang sai và hơn trạng thái khác sẽ được thực thi. Tuy nhiên, nếu khoảng thời gian không bao giờ đúng, mệnh đề khác vẫn sẽ được thực thi.
dùng597608

pseudocode Vì vậy, hãy sửa tôi nếu tôi sai, nhưng điều này hoàn toàn giống với while {} something ngoại trừ việc nó somethingsẽ bị bỏ qua nếu bạn breaktrong whilevòng lặp.
Daniel Kaplan

2
Có lẽ mã giả chính xác nhất sẽ là: while (True) {if (cond) {handle_true (); } khác {xử lý_false (); phá vỡ; }}
VinGarcia

2
"Đừng vượt qua, đừng thu thập 200", haha, mọi người biết nơi này có một tuổi thơ tốt
Stefan Octavian

102

Các elsekhoản được thực hiện nếu bạn thoát khỏi một khối bình thường, bằng cách nhấn các điều kiện vòng lặp hoặc rơi xuống đáy của một khối try. Nó không được thực thi nếu bạn breakhoặc returnra khỏi một khối, hoặc đưa ra một ngoại lệ. Nó hoạt động không chỉ trong khi và cho các vòng lặp, mà còn thử các khối.

Bạn thường tìm thấy nó ở những nơi mà thông thường bạn sẽ thoát khỏi một vòng lặp sớm và việc chạy hết vòng lặp là một dịp bất ngờ / bất thường. Ví dụ: nếu bạn đang lặp qua một danh sách đang tìm kiếm một giá trị:

for value in values:
    if value == 5:
        print "Found it!"
        break
else:
    print "Nowhere to be found. :-("

1
Trên thực tế một cấu trúc khá hữu ích cho một điều như vậy. Không biết bao nhiêu lần tôi đã đặt found_it=Falseở đầu vòng lặp, và sau đó thực hiện kiểm tra nếu found_itkết thúc
Cruncher

42

Trả lời Is there a specific reason?, đây là một ứng dụng thú vị: thoát ra khỏi nhiều cấp độ vòng lặp.

Đây là cách nó hoạt động: vòng lặp bên ngoài có một ngắt ở cuối, vì vậy nó sẽ chỉ được thực hiện một lần. Tuy nhiên, nếu vòng lặp bên trong hoàn thành (không tìm thấy ước số), thì nó sẽ đạt được câu lệnh khác và không thể đạt được sự phá vỡ bên ngoài. Bằng cách này, một sự phá vỡ trong vòng lặp bên trong sẽ thoát ra khỏi cả hai vòng, thay vì chỉ một vòng.

for k in [2, 3, 5, 7, 11, 13, 17, 25]:
    for m in range(2, 10):
        if k == m:
            continue
        print 'trying %s %% %s' % (k, m)
        if k % m == 0:
            print 'found a divisor: %d %% %d; breaking out of loop' % (k, m)
            break
    else:
        continue
    print 'breaking another level of loop'
    break
else:
    print 'no divisor could be found!'

Đối với cả hai whileforcác vòng lặp, elsecâu lệnh được thực thi ở cuối, trừ khi breakđược sử dụng.

Trong hầu hết các trường hợp, có nhiều cách tốt hơn để làm điều này (gói nó thành một hàm hoặc đưa ra một ngoại lệ), nhưng cách này hiệu quả!


1
Tôi đã không downvote nhưng tôi nghĩ tôi biết tại sao ai đó đã làm. Bạn không trả lời câu hỏi và bạn đang cung cấp 14 dòng mã chỉ với 2 dòng mô tả. Nếu có liên quan đến câu hỏi bạn đã không nói với chúng tôi ...
BlueEel

1
@BlueEel cảm ơn bạn đã phản hồi! Tôi đã thêm nhiều lời giải thích về mã, và làm cho nó rõ ràng hơn cách câu trả lời này (vì nó trả lời một phần của nó).
Đánh dấu

Bạn đã quản lý để đặt mã của mình trong ngữ cảnh và mặc dù hiện tại bạn không trả lời tất cả các câu hỏi tôi thấy sự liên quan. Tôi nêu lên câu trả lời của bạn vì nó hữu ích cho người mới và người mới (như bản thân tôi liên quan đến trăn). - Cảm ơn, tôi đã học được điều gì đó.
BlueEel

Tôi thích ứng dụng đơn giản - bây giờ tôi thấy tại sao ai đó có thể sử dụng nó. Mặc dù tôi chưa bao giờ thấy cần nó.
gabe

Ví dụ cho thấy việc sử dụng for / other nhưng câu hỏi cụ thể là về while / other.
Ian Goldby

20

Mệnh đề other được thực thi khi điều kiện while ước lượng thành false.

Từ tài liệu :

Câu lệnh while được sử dụng để thực hiện lặp lại miễn là một biểu thức là đúng:

while_stmt ::=  "while" expression ":" suite
                ["else" ":" suite]

Điều này liên tục kiểm tra biểu thức và, nếu nó là sự thật, thực thi bộ đầu tiên; nếu biểu thức là sai (có thể là lần đầu tiên nó được kiểm tra) thì bộ elsemệnh đề, nếu có, được thực thi và vòng lặp kết thúc.

Một breakcâu lệnh được thực thi trong bộ đầu tiên chấm dứt vòng lặp mà không thực hiện bộ elsemệnh đề. Một continuecâu lệnh được thực thi trong bộ đầu tiên bỏ qua phần còn lại của bộ và quay lại để kiểm tra biểu thức.


15

Câu trả lời của tôi sẽ tập trung vào KHI chúng ta có thể sử dụng while / for-other.

Thoạt nhìn, dường như không có gì khác biệt khi sử dụng

while CONDITION:
    EXPRESSIONS
print 'ELSE'
print 'The next statement'

while CONDITION:
    EXPRESSIONS
else:
    print 'ELSE'
print 'The next statement'

Bởi vì print 'ELSE'câu lệnh dường như luôn luôn được thực thi trong cả hai trường hợp (cả khi whilevòng lặp kết thúc hoặc không chạy).

Sau đó, nó chỉ khác khi câu lệnh print 'ELSE'sẽ không được thực thi. Đó là khi có một breakkhối bên trong khối mã bên dướiwhile

In [17]: i = 0

In [18]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
else:
    print 'ELSE'
print 'The next statement'
   ....:
0
1
2
The next statement

Nếu khác với:

In [19]: i = 0

In [20]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
print 'ELSE'
print 'The next statement'
   ....:
0
1
2
ELSE
The next statement

return không thuộc loại này, vì nó có tác dụng tương tự đối với hai trường hợp trên.

tăng ngoại lệ cũng không gây ra sự khác biệt, bởi vì khi nó tăng lên, nơi mã tiếp theo sẽ được thực thi là trong trình xử lý ngoại lệ (ngoại trừ khối), mã trong elsemệnh đề hoặc ngay sau whilemệnh đề sẽ không được thực thi.


4

Tôi biết đây là câu hỏi cũ nhưng ...

Như Raymond Hettinger đã nói, nó nên được gọi while/no_breakthay vì while/else.
Tôi thấy thật dễ dàng để hiểu rằng nếu bạn nhìn vào đoạn trích này.

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
if n == 0:
    print n

Bây giờ thay vì kiểm tra điều kiện sau vòng lặp while, chúng ta có thể trao đổi nó với elsevà loại bỏ kiểm tra đó.

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
else:  # read it as "no_break"
    print n

Tôi luôn đọc nó while/no_breakđể hiểu mã và cú pháp đó có ý nghĩa hơn đối với tôi.


3

Mệnh đề khác chỉ được thực hiện khi điều kiện while trở thành sai.

Dưới đây là một số ví dụ:

Ví dụ 1: Ban đầu điều kiện là sai, vì vậy mệnh đề khác được thực thi.

i = 99999999

while i < 5:
    print(i)
    i += 1
else:
    print('this')

ĐẦU RA:

this

Ví dụ 2: Điều kiện while i < 5 không bao giờ trở thành sai vì i == 3phá vỡ vòng lặp, vì vậy mệnh đề other không được thực thi.

i = 0

while i < 5:
    print(i)
    if i == 3:
        break
    i += 1
else:
    print('this')

ĐẦU RA:

0
1
2
3

Ví dụ 3: Điều kiện while i < 5 trở thành sai khi i5, vì vậy mệnh đề khác được thực thi.

i = 0

while i < 5:
    print(i)
    i += 1
else:
    print('this')

ĐẦU RA:

0
1
2
3
4
this

0

Câu else:lệnh được thực thi khi và chỉ khi vòng lặp while không còn đáp ứng điều kiện của nó (trong ví dụ của bạn, khi n != 0sai).

Vì vậy, đầu ra sẽ là thế này:

5
4
3
2
1
what the...

Tôi biết nhưng loại này trong khi / khác không hoạt động trong Java. Tôi thấy nó khá thú vị khi tôi tìm ra nó hoạt động trong Python. Tôi chỉ tò mò và muốn biết lý do kỹ thuật.
Ivan

6
@Ivan: Nó không quá nhiều đến nỗi nó không hoạt động trong Java nhưng nó không tồn tại trong Java. Nó có thể được thực hiện để làm việc, nếu ai đó quan tâm để thêm nó vào ngôn ngữ.
Ignacio Vazquez-Abrams

1
Không, trong khi Sai: .. khác .. vẫn chạy mệnh đề khác. Nói chính xác hơn: người khác chỉ không chạy nếu vòng lặp bị hỏng.
Leo Ufimtsev

0

Khác được thực hiện nếu vòng lặp while không phá vỡ.

Tôi muốn nghĩ về nó với phép ẩn dụ của "người chạy bộ".

"Khác" giống như vượt qua vạch đích, không liên quan đến việc bạn bắt đầu ở đầu hay cuối đường đua. "Khác" chỉ không được thực thi nếu bạn ngắt ở đâu đó ở giữa.

runner_at = 0 # or 10 makes no difference, if unlucky_sector is not 0-10
unlucky_sector = 6
while runner_at < 10:
    print("Runner at: ", runner_at)
    if runner_at == unlucky_sector:
        print("Runner fell and broke his foot. Will not reach finish.")
        break
    runner_at += 1
else:
    print("Runner has finished the race!") # Not executed if runner broke his foot.

Các trường hợp sử dụng chính là sử dụng việc thoát ra khỏi các vòng lặp lồng nhau hoặc nếu bạn muốn chạy một số câu lệnh chỉ khi vòng lặp không bị hỏng ở đâu đó (hãy nghĩ rằng việc phá vỡ là một tình huống bất thường).

Ví dụ, sau đây là một cơ chế về cách thoát ra khỏi vòng lặp bên trong mà không cần sử dụng biến hoặc thử / bắt:

for i in [1,2,3]:
    for j in ['a', 'unlucky', 'c']:
        print(i, j)
        if j == 'unlucky':
            break
    else: 
        continue  # Only executed if inner loop didn't break.
    break         # This is only reached if inner loop 'breaked' out since continue didn't run. 

print("Finished")
# 1 a
# 1 b
# Finished

-1

Việc sử dụng tốt hơn 'while: other:' xây dựng trong Python sẽ là nếu không có vòng lặp nào được thực thi trong 'while' thì câu lệnh 'other' được thực thi. Cách thức hoạt động ngày hôm nay không có ý nghĩa gì vì bạn có thể sử dụng mã dưới đây với cùng kết quả ...

n = 5
while n != 0:
    print n
    n -= 1
print "what the..."

8
Không, sự khác biệt là elsekhối sẽ không được thực thi nếu bạn rời khỏi vòng lặp bằng cách sử dụng breakhoặc returntừ khóa. Trong ví dụ của bạn, printcũng sẽ được thực hiện nếu vòng lặp kết thúc trên breaklệnh.
notsurewhattodo

2
Bạn mô tả cách hầu hết mọi người mong muốn rằng tính năng này hoạt động chứ không phải cách nó thực sự hoạt động!
dotancohen

-2

Nó rất hữu ích cho sự tương tác xã hội.

while (Date != "January 1st"):
    time.sleep(1)
else:
    print("Happy new year!")

2
Và chính xác mục đích của elseđây là gì? Các mã làm chính xác như nhau mà không có nó.
wovano

Nếu đồng hồ và lịch breakcủa bạn trong thời gian đếm ngược, không sử dụng elsesẽ khiến bạn nói "Chúc mừng năm mới!" ngay lập tức mà không có ý nghĩa gì.
Hướng dẫn

@Guimote, bạn có ý nghĩa gì với "nếu đồng hồ và lịch của bạn break"? Không có breaktrong mã.
wovano
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.