On this page
*args, **kwargs & การ Unpack
เขียนฟังก์ชันที่รับ argument ได้ยืดหยุ่น และกระจายข้อมูลเข้า/ออกด้วย * และ **
บางฟังก์ชันต้องรับ argument จำนวนไม่แน่นอน เช่น print() รับกี่ตัวก็ได้ บทย่อยนี้สอนวิธีเขียนฟังก์ชันแบบนั้นด้วย *args และ **kwargs พร้อมเทคนิค unpacking ที่ใช้บ่อยมากในโค้ดจริง
positional vs keyword argument
argument ส่งได้ 2 แบบ: ตามตำแหน่ง (positional) หรือระบุชื่อ (keyword) และตั้งค่า default ได้
def greet(name, greeting="สวัสดี"): # greeting มี default
return f"{greeting} {name}"
print(greet("Aph")) # สวัสดี Aph (ใช้ default)
print(greet("Aph", "หวัดดี")) # หวัดดี Aph (positional)
print(greet("Aph", greeting="ยินดี")) # ยินดี Aph (keyword)*args — รับ positional ไม่จำกัดจำนวน
ใส่ * หน้าชื่อพารามิเตอร์ Python จะรวบ argument ที่เหลือทั้งหมดมาเป็น tuple ชื่อ args นิยมตั้งชื่อ args แต่จริง ๆ ชื่ออะไรก็ได้ ที่สำคัญคือ *
def total(*nums): # nums เป็น tuple ของทุกตัวที่ส่งมา
print(nums)
return sum(nums)
print(total(1, 2, 3)) # (1, 2, 3) แล้วคืน 6
print(total(10, 20)) # (10, 20) แล้วคืน 30
print(total()) # () แล้วคืน 0**kwargs — รับ keyword ไม่จำกัดจำนวน
ใส่ ** หน้าชื่อ Python จะรวบ keyword argument ที่เหลือมาเป็น dict นิยมตั้งชื่อ kwargs (keyword arguments)
def make_user(**info): # info เป็น dict
print(info)
return info
make_user(name="Aph", age=25, city="Bangkok")
# {'name': 'Aph', 'age': 25, 'city': 'Bangkok'}
# รวมทุกแบบเข้าด้วยกัน (ลำดับสำคัญ: ปกติ, *args, **kwargs)
def log(level, *messages, **meta):
print(level, messages, meta)
log("INFO", "started", "ok", user="aph", code=200)
# INFO ('started', 'ok') {'user': 'aph', 'code': 200}unpacking: กระจาย list/dict ตอนเรียก
* และ ** ใช้ "ขาออก" ได้ด้วย — กระจาย list เป็น positional args หรือ dict เป็น keyword args ตอนเรียกฟังก์ชัน
def add(a, b, c):
return a + b + c
nums = [1, 2, 3]
print(add(*nums)) # 6 — กระจาย list เป็น a=1, b=2, c=3
opts = {"a": 1, "b": 2, "c": 3}
print(add(**opts)) # 6 — กระจาย dict เป็น keyword
# ใช้บ่อยกับ print
words = ["a", "b", "c"]
print(*words) # a b c (แทน print(words[0], words[1]...))keyword-only argument (บังคับระบุชื่อ)
ใส่ * เปล่า ๆ คั่น เพื่อบังคับให้ argument หลังจากนั้นต้องส่งแบบระบุชื่อเสมอ ป้องกันการส่งผิดตำแหน่ง
def connect(host, *, port, timeout=30):
print(host, port, timeout)
connect("localhost", port=8080) # ✅ ต้องระบุ port=
# connect("localhost", 8080) # ❌ TypeErrorอย่าใช้ list/dict เป็นค่า default เช่น def f(items=[]) เพราะ default ถูกสร้างครั้งเดียวตอนนิยามฟังก์ชัน แล้วถูกใช้ร่วมกันทุกครั้งที่เรียก! ค่าจะค้างข้ามการเรียก วิธีแก้: ใช้ None แล้วสร้างใหม่ข้างใน (เราจะเจาะลึกเรื่องนี้ในหัวข้อ Mutability)
# ❌ ผิด: list ถูกแชร์ข้ามการเรียก
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("a")) # ['a']
print(add_item("b")) # ['a', 'b'] ← ค้าง! ไม่ใช่ ['b']
# ✅ ถูก: ใช้ None แล้วสร้างใหม่
def add_item_ok(item, items=None):
if items is None:
items = []
items.append(item)
return itemsสรุปหัวข้อนี้
- *args รวบ positional เป็น tuple, **kwargs รวบ keyword เป็น dict
- ลำดับพารามิเตอร์: ปกติ → *args → **kwargs
- ตอนเรียก *list กระจายเป็น positional, **dict กระจายเป็น keyword
- * เปล่า ๆ บังคับ keyword-only; ห้ามใช้ list/dict เป็น default
1) เขียนฟังก์ชัน multiply(*nums) คูณทุกตัวเข้าด้วยกัน 2) เขียนฟังก์ชันรับ **kwargs แล้ว print ทุก key=value 3) มี list [3, 5, 7] ใช้ unpacking ส่งเข้าฟังก์ชัน add(a,b,c) 4) แก้ฟังก์ชันที่ใช้ items=[] เป็นแบบ items=None ให้ถูกต้อง