Args, Kwargs และ Parameter
Parameter และ argument
หัวข้อที่มีชื่อว่า “Parameter และ argument”Python แยกความแตกต่างระหว่าง parameter (ชื่อที่อยู่ในนิยามของ function) กับ argument (ค่าที่ส่งเข้าไปตอนเรียกใช้) Python ให้เราควบคุมได้อย่างละเอียดว่าผู้เรียกจะส่งค่าเหล่านั้นเข้ามาได้อย่างไร
Positional และ keyword argument
หัวข้อที่มีชื่อว่า “Positional และ keyword argument”โดยปกติแล้ว ทุก parameter สามารถส่งค่าแบบ positional หรือแบบระบุชื่อ keyword ก็ได้
def connect(host: str, port: int, timeout: int = 30) -> str: return f"{host}:{port} (timeout={timeout}s)"
# Positionalconnect("localhost", 5432)
# Keyword — order does not matterconnect(port=5432, host="localhost")
# Mixed — positional first, then keywordconnect("localhost", port=5432, timeout=60)timeout มี ค่า default เป็น 30 จึงเป็นค่าที่ใส่หรือไม่ก็ได้
positional argument จะต้องมาก่อน keyword argument เสมอ ณ จุดที่เรียกใช้
Variadic positional args: *args
หัวข้อที่มีชื่อว่า “Variadic positional args: *args”ใส่ * นำหน้า parameter เพื่อรวบ positional argument จำนวนเท่าใดก็ได้เข้ามาเป็น tuple
def total(*amounts: float) -> float: return sum(amounts)
print(total(10.0, 20.5, 5.0)) # 35.5print(total()) # 0.0Variadic keyword args: **kwargs
หัวข้อที่มีชื่อว่า “Variadic keyword args: **kwargs”ใส่ ** นำหน้า parameter เพื่อรวบ keyword argument จำนวนเท่าใดก็ได้เข้ามาเป็น dict
def log_event(event: str, **metadata) -> None: parts = [f"event={event}"] for key, value in metadata.items(): parts.append(f"{key}={value}") print(", ".join(parts))
log_event("login", user_id=42, ip="127.0.0.1")# event=login, user_id=42, ip=127.0.0.1Parameter แบบ keyword-only
หัวข้อที่มีชื่อว่า “Parameter แบบ keyword-only”parameter ใด ๆ ที่อยู่ หลัง * เปล่า ๆ (หรือหลัง *args) จะส่งค่าได้ผ่าน keyword เท่านั้น ส่งแบบ positional ไม่ได้
วิธีนี้ทำให้ API อธิบายตัวเองได้ในตัว และป้องกันความผิดพลาดเรื่องลำดับของ argument
def send_email(to: str, subject: str, *, cc: str = "", bcc: str = "") -> None: print(f"To: {to} | Subject: {subject} | CC: {cc} | BCC: {bcc}")
# Calling send_email("[email protected]", "Hi", "[email protected]") would raise TypeErrorลำดับ parameter ทั้งหมด
หัวข้อที่มีชื่อว่า “ลำดับ parameter ทั้งหมด”ลำดับของชนิด parameter ในนิยามจะต้องเป็นแบบนี้เสมอ:
- Positional-or-keyword (
x,y) *args(หรือ*เปล่า ๆ)- Keyword-only (
key=valueหลัง*) **kwargs
def describe( name: str, *adjectives: str, separator: str = ", ", **extras) -> str: adj_str = separator.join(adjectives) if adjectives else "no adjectives" extra_str = ", ".join(f"{k}={v}" for k, v in extras.items()) result = f"{name}: {adj_str}" if extra_str: result += f" ({extra_str})" return result
print(describe("Python"))print(describe("Python", "fast", "readable"))print(describe("Python", "fast", "readable", separator=" | "))print(describe("Python", "fast", separator=" + ", version="3.11", typed=True))Loading Python runtime (first run only)…