Siapa pun yang bermain-main dengan Python cukup lama telah digigit (atau tercabik-cabik) oleh masalah berikut:
def foo(a=[]):
a.append(5)
return a
Pemula Python harapkan fungsi ini untuk selalu kembali daftar dengan hanya satu elemen: [5]
. Hasilnya malah sangat berbeda, dan sangat mencengangkan (untuk pemula):
>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()
Seorang manajer saya pernah mengalami pertemuan pertama dengan fitur ini, dan menyebutnya "cacat desain dramatis" bahasa. Saya menjawab bahwa perilaku itu memiliki penjelasan yang mendasarinya, dan memang sangat membingungkan dan tidak terduga jika Anda tidak memahami bagian dalam. Namun, saya tidak dapat menjawab (untuk diri saya sendiri) pertanyaan berikut: apa alasan untuk mengikat argumen default pada definisi fungsi, dan bukan pada eksekusi fungsi? Saya ragu perilaku yang berpengalaman memiliki penggunaan praktis (yang benar-benar menggunakan variabel statis dalam C, tanpa membiakkan bug?)
Edit :
Baczek membuat contoh yang menarik. Bersama dengan sebagian besar komentar Anda dan Utaal khususnya, saya menjabarkan lebih lanjut:
>>> def a():
... print("a executed")
... return []
...
>>>
>>> def b(x=a()):
... x.append(5)
... print(x)
...
a executed
>>> b()
[5]
>>> b()
[5, 5]
Bagi saya, tampaknya keputusan desain itu relatif terhadap di mana menempatkan lingkup parameter: di dalam fungsi atau "bersama" dengannya?
Melakukan pengikatan di dalam fungsi akan berarti bahwa x
secara efektif terikat ke default yang ditentukan ketika fungsi dipanggil, tidak didefinisikan, sesuatu yang akan menghadirkan cacat yang dalam: def
garis akan menjadi "hibrid" dalam arti bahwa bagian dari pengikatan (dari objek fungsi) akan terjadi pada definisi, dan bagian (penugasan parameter default) pada waktu pemanggilan fungsi.
Perilaku aktual lebih konsisten: semua baris itu akan dievaluasi ketika garis dieksekusi, artinya pada definisi fungsi.
[5]
" Saya seorang pemula Python, dan saya tidak akan mengharapkan ini, karena jelas foo([1])
akan kembali [1, 5]
, tidak [5]
. Apa yang ingin Anda katakan adalah bahwa seorang pemula akan mengharapkan fungsi yang dipanggil tanpa parameter akan selalu kembali [5]
.