2.12. ลูป

ลูป รันบล็อกโค้ดเดิมซ้ำๆ Python มีสองรูปแบบ: while ที่ทำงานต่อไปตราบเท่าที่เงื่อนไขยังเป็นจริง และ for ที่วนผ่านรายการในลำดับ

Side-by-side flowcharts. while: test the condition, run the body if true, repeat. for: take the next item from the iterable, run the body, repeat until exhausted.

while ทดสอบเงื่อนไขต่อเนื่อง; for วนผ่านลำดับจนหมด

2.12.1. ลูป while

ลูป while ทดสอบเงื่อนไขก่อนแต่ละรอบและรัน body จนกว่าการทดสอบจะเป็นเท็จ:

count = 0
while count < 5:
    print(count)
    count += 1

Output:

0
1
2
3
4

หากเงื่อนไขเป็นจริงตั้งแต่ต้นและไม่เคยเป็นเท็จ ลูปจะทำงานตลอดไป while True: เป็น idiom มาตรฐานสำหรับ main loop ที่ออกโดยใช้ break อย่างชัดเจน:

while True:
    step()
    if done():
        break

2.12.2. ลูป for

ลูป for วนผ่านรายการของ iterable ไม่ว่าจะเป็น list, tuple, string, bytes, dict หรืออะไรก็ตามที่รองรับ iteration:

for fruit in ["apple", "banana", "cherry"]:
    print(fruit)

Output:

apple
banana
cherry

รูปแบบเดียวกันใช้ได้กับ string โดยแต่ละรายการคือ string ขนาดหนึ่งตัวอักษร:

for letter in "OpenMV":
    print(letter)

Output:

O
p
e
n
M
V

การวนซ้ำ dict โดยตรงจะให้ keys ตามลำดับการแทรก:

for key in {"a": 1, "b": 2}:
    print(key)

Output:

a
b

แต่ละรอบจะผูกตัวแปรลูป (fruit, letter, key) กับรายการถัดไป หลังจากลูปสิ้นสุด ตัวแปรจะเก็บค่าจากรอบสุดท้าย

2.12.3. range

สำหรับลูปที่วนตามช่วงตัวเลข ให้ใช้ range():

  • range(stop) -- 0, 1, ..., stop - 1

  • range(start, stop) -- start, start + 1, ..., stop - 1

  • range(start, stop, step) -- พร้อม step ที่กำหนดเอง (ค่าลบนับถอยหลัง)

for i in range(5):           # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):     # 2, 4, 6
    print(i)

for i in range(10, 0, -1):   # 10, 9, ..., 1
    print(i)

range() สร้างค่าแบบ lazy -- ไม่สร้าง list ในหน่วยความจำ หากต้องการ list จริงๆ ให้ครอบ: list(range(10))

2.12.4. enumerate

เมื่อลูปต้องการทั้ง index และรายการ enumerate() จะ yield คู่ (index, item):

for i, name in enumerate(["a", "b", "c"]):
    print(i, name)
# 0 a
# 1 b
# 2 c

เริ่ม index ที่ค่าอื่นที่ไม่ใช่ศูนย์โดยส่งอาร์กิวเมนต์ที่สอง: enumerate(items, start=1)

2.12.5. zip

หากต้องการวนสอง iterable (หรือมากกว่า) พร้อมกัน ให้ใช้ zip() โดยจะ yield หนึ่ง tuple ต่อตำแหน่งและหยุดที่ input ที่สั้นที่สุด:

names  = ["alice", "bob", "carol"]
scores = [88, 92, 70]

for name, score in zip(names, scores):
    print(name, score)

Output:

alice 88
bob 92
carol 70

2.12.6. การกำหนดค่าแบบ inline ด้วย :=

ตัวดำเนินการ walrus := คือการกำหนดค่าที่เป็น expression ด้วย โดยจะผูกชื่อและประเมินค่าเดียวกันในเวลาเดียวกัน ในลูป while สิ่งนี้รวม pattern "อ่าน ตรวจสอบ body" ที่พบบ่อยให้เป็นบรรทัดเดียว:

# without walrus
value = next_value()
while value is not None:
    process(value)
    value = next_value()

# with walrus
while (value := next_value()) is not None:
    process(value)

ทั้งสองรูปแบบทำสิ่งเดียวกัน ใช้ := เมื่อการซ้ำซ้อนของการกำหนดค่าทำให้อ่านยากจริงๆ อย่าใช้เพื่อโชว์ความฉลาดเท่านั้น วงเล็บจำเป็นในตำแหน่งส่วนใหญ่เพื่อให้ expression ไม่กำกวม