ทุกคนที่มี Python นานพอถูกกัด (หรือฉีกเป็นชิ้น ๆ ) โดยปัญหาต่อไปนี้:
def foo(a=[]):
a.append(5)
return a
[5]
สามเณรงูใหญ่คาดว่าจะได้ฟังก์ชั่นนี้เสมอกลับรายการที่มีเพียงองค์ประกอบหนึ่ง: ผลลัพธ์จะแตกต่างกันมากและน่าประหลาดใจมาก (สำหรับมือใหม่):
>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()
ผู้จัดการของฉันเคยพบกับคุณสมบัตินี้ครั้งแรกและเรียกมันว่า "ข้อบกพร่องในการออกแบบที่น่าทึ่ง" ของภาษา ฉันตอบว่าพฤติกรรมนั้นมีคำอธิบายพื้นฐานและเป็นเรื่องที่ทำให้งงงวยและคาดไม่ถึงถ้าคุณไม่เข้าใจ internals อย่างไรก็ตามฉันไม่สามารถตอบคำถามต่อไปนี้ (กับตัวเอง): อะไรคือเหตุผลในการเชื่อมอาร์กิวเมนต์เริ่มต้นที่คำจำกัดความของฟังก์ชั่นและไม่ทำงานในการดำเนินการ? ฉันสงสัยว่าพฤติกรรมที่มีประสบการณ์นั้นมีประโยชน์ในทางปฏิบัติ (ใครใช้ตัวแปรคงที่ใน C โดยไม่ต้องปรับปรุงบั๊ก)
แก้ไข :
Baczek เป็นตัวอย่างที่น่าสนใจ เมื่อรวมกับความคิดเห็นและ Utaal ของคุณโดยเฉพาะฉันขออธิบายเพิ่มเติม:
>>> def a():
... print("a executed")
... return []
...
>>>
>>> def b(x=a()):
... x.append(5)
... print(x)
...
a executed
>>> b()
[5]
>>> b()
[5, 5]
สำหรับฉันดูเหมือนว่าการตัดสินใจการออกแบบนั้นสัมพันธ์กับตำแหน่งที่จะวางขอบเขตของพารามิเตอร์: ภายในฟังก์ชันหรือ "ร่วมกัน" ด้วยหรือไม่
ทำผูกพันภายในฟังก์ชั่นจะหมายความว่าx
มีผลผูกพันกับค่าเริ่มต้นที่ระบุเมื่อฟังก์ชั่นที่เรียกว่าไม่ได้กำหนดสิ่งที่จะนำเสนอข้อบกพร่องลึก: def
บรรทัดจะเป็น "ลูกผสม" ในแง่ที่เป็นส่วนหนึ่งของการผูก วัตถุฟังก์ชั่น) จะเกิดขึ้นที่คำจำกัดความและส่วนหนึ่ง (การกำหนดพารามิเตอร์เริ่มต้น) ที่เวลาเรียกใช้ฟังก์ชั่น
พฤติกรรมที่เกิดขึ้นจริงนั้นสอดคล้องกันมากขึ้น: ทุกอย่างในบรรทัดนั้นจะถูกประเมินเมื่อประมวลผลบรรทัดนั้นซึ่งหมายถึงนิยามของฟังก์ชัน
[5]
" ฉันเป็นสามเณรงูหลามและฉันจะไม่คาดหวังนี้เพราะเห็นได้ชัดว่าfoo([1])
จะกลับมาไม่ได้[1, 5]
[5]
สิ่งที่คุณหมายถึงการบอกก็คือว่าเป็นสามเณรคาดว่าจะได้ฟังก์ชั่นเรียกว่ามีพารามิเตอร์ไม่มี[5]
มักจะกลับ