2.30. Comprehensions¶
comprehension สร้าง list, set, dict หรือ generator ใหม่จาก iterable ที่มีอยู่ในนิพจน์เดียว เป็นการแทนที่รูปแบบทั่วไปของการเริ่มต้นด้วยคอนเทนเนอร์ว่างเปล่าและการ append ในลูป
2.30.1. List comprehensions¶
squares = [x * x for x in range(5)]
print(squares)
ผลลัพธ์:
[0, 1, 4, 9, 16]
ลูปเดียวกันที่เขียนแบบขยาย:
squares = []
for x in range(5):
squares.append(x * x)
รูปแบบ comprehension เป็นนิพจน์เดียวที่สร้าง list ในที่เดียว ไม่มี squares = [] และไม่มี .append -- ผลลัพธ์คือค่าของ comprehension
นิพจน์นำหน้าผลิตแต่ละรายการ; ส่วน for clause ตั้งชื่อตัวแปรลูป; if เพิ่มเติมเพื่อกรองรายการออก¶
2.30.2. การกรองด้วย if¶
ส่วน if เพิ่มเติมเก็บเฉพาะรายการที่ตรงกัน:
evens = [x for x in range(10) if x % 2 == 0]
print(evens)
ผลลัพธ์:
[0, 2, 4, 6, 8]
ตัวกรองทำงานก่อนนิพจน์นำหน้า -- x % 2 == 0 ถูกตรวจสอบก่อน; เฉพาะค่าที่ตรงกันเท่านั้นที่ถึง x สำหรับผลลัพธ์
2.30.3. Dict และ set comprehensions¶
รูปแบบเดียวกันใช้งานได้กับ dict และ set literal
dict comprehension มีคู่ key: value ก่อน for:
squares = {x: x * x for x in range(5)}
print(squares)
ผลลัพธ์:
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
set comprehension ใช้วงเล็บปีกกาและนิพจน์เดียว:
unique_lengths = {len(w) for w in ["a", "bb", "c", "bb"]}
print(unique_lengths)
ผลลัพธ์:
{1, 2}
2.30.4. Generator expressions¶
วงเล็บกลมผลิต generator expression แทน list ค่าถูกคำนวณทีละหนึ่งตามความต้องการ:
total = sum(x * x for x in range(1000))
ไม่มี list ล้านรายการถูกสร้างขึ้นเลย ค่าไหลทีละหนึ่งเข้าสู่ sum() ซึ่งบวกและทิ้งแต่ละค่าไปเรื่อยๆ
Generator expression เป็นตัวเลือกที่เหมาะสมเมื่อป้อนค่าเข้าสู่ฟังก์ชันรีดิวซ์ (sum(), max(), any(), all()) หรือโค้ดที่บริโภค iterator อื่นๆ -- ประหยัดหน่วยความจำที่ list เทียบเท่าจะใช้
2.30.5. เมื่อ ไม่ควร ใช้ comprehension¶
Comprehension กระชับแต่ไม่ชัดเจนเสมอ ใช้ลูป for ธรรมดาเมื่อ:
เนื้อหาต้องการมากกว่าหนึ่งคำสั่ง (comprehension พอดีกับนิพจน์เดียว)
เนื้อหามี side effect (การพิมพ์, การเขียนลงไฟล์) -- comprehension ใช้สำหรับ สร้าง คอลเลกชัน ไม่ใช่สำหรับรันการกระทำ
ตัวกรองหรือการแปลงมีหลายส่วนมากจนทำให้ comprehension ไม่ได้อ่านจากซ้ายไปขวาอีกต่อไป