2.13. การควบคุมลูป¶
คีย์เวิร์ดสองตัวเปลี่ยนวิธีการทำงานของลูป:
break-- ออกจากลูปทันทีcontinue-- ข้ามส่วนที่เหลือของรอบปัจจุบันและเริ่มรอบถัดไป
ทั้งสองใช้กับลูป ในสุด ที่ปรากฏอยู่
2.13.1. break¶
ใช้ break เพื่อหยุดลูปทันทีที่เงื่อนไขเป็นจริง รูปแบบ "ค้นหาและหยุด" แบบคลาสสิก:
found = None
for item in items:
if matches(item):
found = item
break
if found is not None:
print("found:", found)
ในลูป while True: นั้น break คือวิธีสิ้นสุดลูป:
while True:
line = next_line()
if line == "quit":
break
process(line)
2.13.2. continue¶
ใช้ continue เพื่อข้ามส่วนที่เหลือของ body และกระโดดไปยังรอบถัดไป เหมาะสำหรับการกรองรายการภายในลูป:
for n in numbers:
if n < 0:
continue # skip negatives
print(n)
ผลลัพธ์เดียวกันสามารถเขียนเป็นบล็อก if ที่ครอบ body ส่วนที่เหลือ continue บางครั้งชัดเจนกว่าเมื่อเงื่อนไขสำหรับข้ามระบุได้ง่ายกว่าเงื่อนไขสำหรับเก็บไว้
ภายในลูป continue มีบทบาทเดียวกับ return ก่อนกำหนดในฟังก์ชัน: ข้ามกรณีที่ไม่ต้องการจัดการและรักษางานหลักให้อยู่ในระดับ indent ด้านนอก รูปแบบลูปกรอง-และ-ประมวลผลคือรูปแบบมาตรฐาน:
for item in items:
if item is None:
continue
if not item.is_valid():
continue
process(item)
บรรทัด process(item) ที่เยื้องเข้าไปคืองานจริง แต่ละ guard ด้านบนระบุอย่างชัดเจนว่ารายการใดถูกข้าม
2.13.3. else ในลูป¶
ทั้ง for และ while รองรับบล็อก else แบบไม่บังคับ โดยจะทำงานเมื่อลูปจบ โดยไม่ กด break การใช้งานที่พบบ่อยที่สุดคือลูปค้นหาที่ต้องการค่าสำรองหากไม่พบสิ่งที่ต้องการ:
for item in items:
if matches(item):
print("found:", item)
break
else:
print("no match")
หาก break ทำงาน บล็อก else จะถูกข้าม อ่านโครงสร้างนี้ว่า "for X in Y: ...; or-else หากเราไม่เคย break ออกมา ให้ทำ Z"
2.13.4. รูปแบบลูปที่พบบ่อย¶
รูปแบบบางอย่างปรากฏบ่อยในสคริปต์จริง:
Polling -- รอให้เงื่อนไขบางอย่างเป็นจริงก่อนดำเนินการต่อ body ใช้
passซึ่งเป็นคำสั่ง no-op ของ Python; ทุกบล็อกที่เยื้องเข้าต้องมีคำสั่งอย่างน้อยหนึ่งคำสั่ง และpassคือวิธีบอกว่า "ไม่ต้องทำอะไรที่นี่":while not ready(): pass proceed()
State machine -- ลูป
while True:เดียวที่เลือกสิ่งที่จะทำตามตัวแปร state มีประโยชน์เมื่องานแบ่งออกเป็นขั้นตอนที่มีชื่อชัดเจน:state = "header" for line in lines: if state == "header": if line.startswith("---"): state = "body" elif state == "body": print(line)
Accumulating -- สร้างผลลัพธ์ขึ้นมาขณะวนผ่านลำดับ:
total = 0 for x in samples: total += x mean = total / len(samples)
ลูปสะสมหลายรูปแบบมีเทียบเท่าแบบบรรทัดเดียวโดยใช้ built-in เลือกใช้ built-in เมื่อมีให้ใช้:
sum()-- รวมทุกรายการใน iterableany()--Trueหากมีอย่างน้อยหนึ่งรายการที่เป็น truthyall()--Trueเฉพาะเมื่อทุกรายการเป็น truthysorted()-- list ใหม่ที่มีรายการเรียงตามลำดับlen()-- จำนวนรายการ (เมื่อ iterable รู้ความยาวของตัวเอง)
>>> samples = [3, 1, 4, 1, 5, 9, 2, 6] >>> sum(samples) 31 >>> sum(samples) / len(samples) # mean 3.875 >>> max(samples) 9 >>> min(samples) 1 >>> sorted(samples) [1, 1, 2, 3, 4, 5, 6, 9] >>> any([False, False, True]) True >>> all([True, True, False]) False
เวอร์ชัน built-in สั้นกว่า ชัดเจนกว่า และมักเร็วกว่าการเขียนลูปเองด้วยมือ