Unpacking ใน Python: ตัวแปรมีดาว สลับค่า และแยกข้อมูลซ้อน
บทเรียนนี้แปลจากต้นฉบับภาษาอังกฤษRead in EnglishLeer en españolЧитать на русскомLer em portuguêsแจ้งข้อผิดพลาดในการแปล
ลองนึกว่าคุณสั่งพัสดุออนไลน์ที่มีของสามชิ้น: หนังสือ หูฟัง และเคสโทรศัพท์ เมื่อกล่องมาถึง คุณเปิดกล่องแล้ววางของแต่ละชิ้นไว้ในที่ของมัน หนังสือไปอยู่บนชั้น หูฟังไปอยู่บนโต๊ะ และเคสไปสวมที่โทรศัพท์
การแยกค่า (unpacking) ใน Python ก็ทำงานแบบเดียวกัน คุณนำกลุ่มของค่า ไม่ว่าจะเป็นทูเพิล (tuple) ลิสต์ (list) หรือออบเจกต์ที่วนซ้ำได้ (iterable) ใด ๆ มากำหนดให้ตัวแปรของแต่ละค่าได้ในบรรทัดเดียวที่อ่านง่าย ไม่ต้องดึงสมาชิกทีละตัวด้วยดัชนี
ในบทเรียนนี้ คุณจะได้เรียนการแยกค่าแบบพื้นฐาน เทคนิคสลับค่าตัวแปรแบบเรียบง่าย นิพจน์แบบมีดาว (starred expression) ที่เก็บสมาชิกได้หลายตัว การแยกค่าภายในลูป และวิธีแยกค่าจากข้อมูลที่ซ้อนกัน
การแยกค่าแบบพื้นฐานทำงานอย่างไร
เมื่อคุณมีทูเพิลหรือลิสต์ที่มีหลายค่า คุณกำหนดแต่ละค่าให้ตัวแปรแยกกันได้ในบรรทัดเดียว จำนวนตัวแปรทางซ้ายต้องเท่ากับจำนวนสมาชิกทางขวา
10 20 30 red green blue
ถ้าไม่ใช้การแยกค่า คุณต้องดึงสมาชิกแต่ละตัวด้วยดัชนี การแยกค่าทำให้โค้ดสั้นลงและอ่านง่ายขึ้นมาก
point = (10, 20, 30)
x = point[0]
y = point[1]
z = point[2]
print(x, y, z)point = (10, 20, 30)
x, y, z = point
print(x, y, z)คุณยังแยกค่าในการกำหนดค่าได้โดยตรง โดยไม่ต้องสร้างทูเพิลแล้วเก็บไว้ในตัวแปรก่อน Python จะสร้างทูเพิลให้อัตโนมัติเมื่อคุณคั่นค่าด้วยจุลภาค
Alice 25 Paris <class 'tuple'>
วิธีสลับค่าตัวแปรในบรรทัดเดียว
ในภาษาโปรแกรมส่วนใหญ่ การสลับค่าตัวแปรสองตัวต้องใช้ตัวแปรชั่วคราว แต่การแยกค่าของ Python ทำให้ไม่ต้องใช้ คุณสลับค่าได้ในบรรทัดเดียวอย่างเรียบร้อย
world hello
วิธีนี้ได้ผลเพราะ Python ประเมินด้านขวาก่อน โดยรวมค่าเป็นทูเพิล (b, a) แล้วจึงแยกค่าใส่ a, b ทั้งหมดเกิดขึ้นอย่างปลอดภัยในขั้นตอนเดียว
a = 1
b = 2
temp = a
a = b
b = temp
print(a, b) # 2 1a = 1
b = 2
a, b = b, a
print(a, b) # 2 1คุณสลับค่าตัวแปรสามตัวหรือมากกว่าได้ด้วยวิธีเดียวกัน Python จัดการทั้งหมดในขั้นตอนเดียว
Before: a=1, b=2, c=3 After: a=2, b=3, c=1
นิพจน์แบบมีดาว (*rest) คืออะไร
บางครั้งคุณไม่รู้แน่ชัดว่ากลุ่มข้อมูลมีสมาชิกกี่ตัว หรือสนใจแค่บางตัวเท่านั้น นิพจน์แบบมีดาว (starred expression) เช่น *variable จะเก็บสมาชิกที่เหลือทั้งหมดไว้ในลิสต์
1 [2, 3, 4, 5] [1, 2, 3, 4] 5
คุณวางดาวไว้ตรงกลางก็ได้ เหมาะมากเมื่อคุณรู้ว่าต้องการสมาชิกตัวแรกและตัวสุดท้าย แต่อยากข้ามทุกตัวที่อยู่ระหว่างกลาง
First: 95 Middle: [80, 75, 90, 85, 70] Last: 88
10 20 [] H ['e', 'l', 'l'] o
วิธีใช้การแยกค่าในลูป for
การแยกค่าโดดเด่นมากในลูป for เมื่อวนลูปผ่านลิสต์ของทูเพิล (หรือลิสต์ของลิสต์) คุณแยกค่าของแต่ละรายการใส่ตัวแปรที่ตั้งชื่อไว้ได้ทันที แทนที่จะดึงค่าด้วยดัชนี
Alice is 16 years old Bob is 15 years old Charlie is 17 years old
รูปแบบนี้ใช้บ่อยมากกับ enumerate() และ dict.items() ทั้งสองคืนค่าเป็นทูเพิล และการแยกค่าทำให้โค้ดอ่านง่ายขึ้นมาก
0: apple 1: banana 2: cherry Alice -> 16 Bob -> 15 Charlie -> 17
วิธีแยกค่าจากโครงสร้างข้อมูลที่ซ้อนกัน
การแยกค่าใน Python ลงลึกได้หลายชั้น ถ้าค่าภายในกลุ่มข้อมูลเป็นทูเพิลหรือลิสต์อีกที คุณแยกค่านั้นได้โดยใช้วงเล็บซ้อนกันทางด้านซ้าย
Alice: 95, 87, 92
วิธีนี้ใช้ได้ทุกระดับความลึก คุณยังรวมการแยกค่าแบบซ้อนเข้ากับนิพจน์แบบมีดาวได้ด้วย: name, (first, *others) = ('Alice', (95, 87, 92)) จะเก็บ 95 ไว้ใน first และ [87, 92] ไว้ใน others
Alice: average = 91.3 Bob: average = 84.3 Charlie: average = 85.3
ข้อผิดพลาดที่พบบ่อยในการแยกค่า
เมื่อจับหลักได้แล้ว การแยกค่าก็เข้าใจง่าย แต่มีกับดักบางอย่างที่ผู้เริ่มต้นมักพลาด
Alice 10 20 42 <class 'list'>
แบบฝึกหัด
แยกค่าทูเพิล point ใส่ตัวแปรสามตัว: x, y และ z จากนั้นแสดงค่าทั้งสามในบรรทัดเดียวโดยคั่นด้วยช่องว่าง โดยใช้ print(x, y, z)
ตัวแปร first และ second เก็บค่าไว้ผิดตัว ให้สลับค่าด้วยรูปแบบการแยกค่าของ Python (บรรทัดเดียว ไม่ใช้ตัวแปรชั่วคราว) แล้วแสดงค่าทั้งสอง
ใช้นิพจน์แบบมีดาวแยกค่าลิสต์ numbers ใส่ head (สมาชิกตัวแรก) และ tail (ที่เหลือทั้งหมด) แล้วแสดงทั้งสองค่าคนละบรรทัด
โค้ดนี้แสดงอะไร? ลองคิดว่าดาวเก็บอะไรไว้ และกลายเป็นข้อมูลชนิดใด
a, *b, c = [1, 2, 3, 4, 5, 6]
print(a)
print(b)
print(c)เขียนคำสั่ง print() สามคำสั่งที่แสดงผลออกมาเหมือนกันทุกตัวอักษร
คุณมีลิสต์ของข้อมูลนักเรียน แต่ละรายการเป็นทูเพิลรูปแบบ (name, (math_score, english_score)) ใช้การแยกค่าแบบซ้อนในลูป for เพื่อคำนวณและแสดงคะแนนเฉลี่ยของนักเรียนแต่ละคน
แสดงแต่ละบรรทัดในรูปแบบ Name: average โดยปัดค่าเฉลี่ยให้เหลือทศนิยม 1 ตำแหน่งด้วย :.1f