Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

วิธีใช้ Star Expression ในการ Unpacking ใน Python

บทนำ

ข้อจำกัดพื้นฐานของ unpacking คือ ต้องรู้ความยาวของ sequence ล่วงหน้า

ปัญหา


random_numbers = [0, 1, 5, 9, 17, 12, 7, 10, 3, 2]
random_numbers_descending = sorted(random_numbers, reverse=True)
# [17, 12, 10, 9, 7, 5, 3, 2, 1, 0]

# พยายาม unpack แค่ 2 ตัวแรก - จะ error
largest, second_largest = random_numbers_descending
# ValueError: too many values to unpack (expected 2)

วิธีเก่า: ใช้ Indexing/Slicing


largest = random_numbers_descending[0]           # 17
second_largest = random_numbers_descending[1]    # 12
rest_of_numbers = random_numbers_descending[2:]  # [10, 9, 7, 5, 3, 2, 1, 0]

วิธีนี้ทำงานได้ แต่โค้ดดู雜乱 (visually noisy) และ error-prone

วิธีที่ดีกว่า: Starred Expression (PEP 3132)

Syntax ดาว (*) รองรับ catch-all unpacking ส่วนที่ไม่ match pattern อื่นจะไปเก็บในตัวแปรที่มี *

ตัวอย่าง 1: ดึง 2 ตัวแรก ที่เหลือไปเก็บใน *rest


largest, second_largest, *rest_of_numbers = random_numbers_descending
print(f"largest: {largest}")           # 17
print(f"second_largest: {second_largest}")  # 12
print(f"rest_of_numbers: {rest_of_numbers}")  # [10, 9, 7, 5, 3, 2, 1, 0]

ตัวอย่าง 2: ดึงตัวแรกและตัวสุดท้าย ที่เหลือไปเก็บใน *rest


largest, *rest_of_numbers, smallest = random_numbers_descending
print(f"largest: {largest}")              # 17
print(f"rest_of_numbers: {rest_of_numbers}")  # [12, 10, 9, 7, 5, 3, 2, 1]
print(f"smallest: {smallest}")            # 0

ตัวอย่าง 3: ดึง 2 ตัวสุดท้าย


*rest_of_numbers, second_smallest, smallest = random_numbers_descending
print(f"rest_of_numbers: {rest_of_numbers}")  # [17, 12, 10, 9, 7, 5, 3, 2]
print(f"second_smallest: {second_smallest}")  # 1
print(f"smallest: {smallest}")                # 0

ข้อจำกัดสำคัญ

  1. ต้องมี required part อย่างน้อย 1 ตัว - ไม่สามารถใช้ *rest = seq ได้ (SyntaxError)
  2. ไม่สามารถมี starred expression หลายตัวในระดับเดียวกัน - *a, *b, c = seq Error
  3. แต่สามารถมีหลาย starred expression ในโครงสร้างหลายระดับ (nested)

ตัวอย่าง Nested Starred Expression


player_grandslame_and_atptitles = {
    'Federer': (20, 103),
    'Nadal': (20, 84),
}
((player1, (grandslam1, *atptitles1)), (player2, (grandslam2, *atptitles2))) = player_grandslame_and_atptitles.items()
print(f'Player - {player1} Have acheived {grandslam1} grandslams and , {atptitles1} atp tour titles')
print(f'Player - {player2} Have acheived {grandslam2} grandslams and , {atptitles2} atp tour titles')

ผลลัพธ์:


Player - Federer Have acheived 20 grandslams and , [103] atp tour titles
Player - Nadal Have acheived 20 grandslams and , [84] atp tour titles

พฤติกรรมของ Starred Expression

  • Starred expression เสมอจะกลายเป็น list
  • ถ้าไม่มี leftover items จะเป็น empty list []
  • เหมาะสำหรับ sequence ที่รู้ว่ามีอย่างน้อย N องค์ประกอบ

random_numbers = [0, 1]
first, second, *rest = random_numbers
print(first, second, rest)  # (0, 1, [])