การจัดการค่าเริ่มต้นของพารามิเตอร์ใน Python เป็นหนึ่งในประเด็นที่ทำให้โปรแกรมเมอร์มือใหม่สับสนบ่อยครั้ง
สาเหตุหลักคือการใช้วัตถุที่ "เปลี่ยนแปลงได้" (mutable) เช่น list หรือ dictionary เป็นค่าเริ่มต้น เนื่องจากค่าเริ่มต้นจะถูกสร้างขึ้นเพียงครั้งเดียวตอนนิยามฟังก์ชัน ไม่ใช่ทุกครั้งที่เรียกใช้
ปัญหาที่พบ
def func(data=[]):
data.append(1)
return data
func() # คืนค่า [1]
func() # คืนค่า [1, 1] ← ค่าสะสมจากการเรียกก่อนหน้า
พฤติกรรมนี้เกิดจาก Python ประเมินค่าเริ่มต้น (default arguments) เพียงครั้งเดียวขณะนิยามฟังก์ชัน ดังนั้นวัตถุ mutable เดียวกันจะถูกใช้ร่วมกันในทุกครั้งที่เรียก
วิธีแก้ไขที่ถูกต้อง
สร้างวัตถุใหม่ทุกครั้งที่เรียกฟังก์ชัน โดยใช้ None เป็นสัญญาณว่าไม่มีอาร์กิวเมนต์ส่งมา
def append2(element, foo=None):
if foo is None:
foo = []
foo.append(element)
return foo
print(append2(12)) # [12]
print(append2(43)) # [43]
ผลลัพธ์ที่คาดหวัง
[12] [43]
แต่ละครั้งที่เรียก append2 จะได้ list ใหม่ที่ไม่ขึ้นกับการเรียกก่อนหน้า