Fungsi apa yang functools.partial
ditawarkan yang tidak bisa Anda dapatkan melalui lambdas?
Tidak banyak dalam hal fungsi tambahan (tapi, lihat nanti) - dan, keterbacaan ada di mata yang melihatnya.
Kebanyakan orang yang terbiasa dengan bahasa pemrograman fungsional (khususnya yang berada dalam keluarga Lisp / Skema) tampaknya sangat menyukai lambda
- saya katakan "sebagian besar", jelas tidak semua, karena Guido dan saya pasti termasuk di antara mereka yang "akrab dengan" (dll. ) namun dianggap lambda
sebagai anomali yang merusak pemandangan di Python ...
Dia menyesal telah menerimanya ke Python sementara berencana untuk menghapusnya dari Python 3, sebagai salah satu "gangguan Python".
Saya sepenuhnya mendukungnya dalam hal itu. (Saya suka lambda
Skema ... sementara keterbatasannya dalam Python , dan cara anehnya hanya tidak dengan sisa bahasa, buat kulit saya merangkak).
Namun tidak demikian bagi gerombolan lambda
kekasih - yang melakukan salah satu hal paling dekat dengan pemberontakan yang pernah terjadi dalam sejarah Python, sampai Guido mundur dan memutuskan untuk pergi lambda
.
Beberapa kemungkinan penambahan functools
(untuk membuat fungsi mengembalikan konstanta, identitas, dll) tidak terjadi (untuk menghindari duplikasi lambda
fungsi yang lebih eksplisit ), meskipun partial
tentu saja tetap (tidak ada duplikasi total , juga tidak merusak pemandangan).
Ingat lambda
tubuh itu terbatas pada ekspresi , jadi punya keterbatasan. Sebagai contoh...:
>>> import functools
>>> f = functools.partial(int, base=2)
>>> f.args
()
>>> f.func
<type 'int'>
>>> f.keywords
{'base': 2}
>>>
functools.partial
Fungsi yang dikembalikan dihiasi dengan atribut yang berguna untuk introspeksi - fungsi yang dibungkus, dan argumen posisional dan bernama apa yang diperbaiki di dalamnya. Lebih jauh, argumen yang dinamai dapat ditimpa segera kembali ("memperbaiki" agaknya, dalam arti, pengaturan default):
>>> f('23', base=10)
23
Jadi, seperti yang Anda lihat, itu pasti tidak sesederhanalambda s: int(s, base=2)
! -)
Ya, Anda dapat memutarbalikkan lambda Anda untuk memberi Anda ini - misalnya, untuk kata kunci-override,
>>> f = lambda s, **k: int(s, **dict({'base': 2}, **k))
tapi saya sangat berharap bahwa bahkan yang paling bersemangat lambda
-lover tidak menganggap kengerian ini lebih mudah dibaca daripada partial
panggilan! -). Bagian "pengaturan atribut" bahkan lebih sulit, karena batasan "tubuh adalah ekspresi tunggal" dari Python lambda
(ditambah fakta bahwa penugasan tidak pernah dapat menjadi bagian dari ekspresi Python) ... Anda akhirnya "memalsukan penugasan dalam ekspresi" dengan memperluas daftar pemahaman jauh melampaui batas desainnya ...:
>>> f = [f for f in (lambda f: int(s, base=2),)
if setattr(f, 'keywords', {'base': 2}) is None][0]
Sekarang gabungkan override-argumen-nama yang dinamai, ditambah pengaturan tiga atribut, ke dalam satu ekspresi, dan katakan betapa mudahnya itu dibaca ...!
functools.partial
yang Anda sebutkan membuatnya lebih unggul daripada lambda. Mungkin ini adalah topik dari posting lain, tetapi apa itu pada tingkat desain yang sangat mengganggu Andalambda
?def
danlambda
kata kunci: buat keduanyafunction
(salah satu pilihan Javascript jadi benar ), dan setidaknya 1/3 keberatan saya akan hilang ! -). Seperti yang saya katakan, saya tidak keberatan dengan lambda di Lisp ...! -)def
. Pemimpin kita yang baik hati telah berbicara!Nah, inilah contoh yang menunjukkan perbedaan:
Pos-pos ini oleh Ivan Moore memperluas "keterbatasan lambda" dan penutupan dengan python:
sumber
lambda y, n=n: ...
. Ikatan yang terlambat (nama-nama yang hanya muncul di badan fungsi, tidak dalamdef
atau fungsi yang setaralambda
) sama sekali bukan bug, seperti yang telah saya tunjukkan panjang lebar dalam jawaban SO di masa lalu: Anda lebih awal mengikat secara eksplisit ketika itu yang Anda inginkan, gunakan default yang mengikat saat itulah yang Anda inginkan, dan itulah pilihan desain yang tepat mengingat konteks sisa desain Python.Dalam versi terbaru Python (> = 2.7), Anda bisa
pickle
apartial
, tetapi bukanlambda
:sumber
multiprocessing.Pool.map()
. stackoverflow.com/a/3637905/195139partial
dapat dipilih dalam Python 2.7.Sebagai jawaban sebagian untuk ini saya memutuskan untuk menguji kinerja. Ini contoh saya:
pada Python 3.3 itu memberi:
Yang berarti bahwa sebagian membutuhkan sedikit lebih banyak waktu untuk pembuatan tetapi jauh lebih sedikit waktu untuk eksekusi. Ini bisa jadi efek dari ikatan awal dan akhir yang dibahas dalam jawaban dari ars .
sumber
partial
ditulis dalam C, daripada Python murni, artinya dapat menghasilkan callable yang lebih efisien daripada hanya membuat fungsi yang memanggil fungsi lain.Selain fungsi ekstra yang disebutkan Alex, keunggulan lain dari functools.partial adalah kecepatan. Dengan parsial Anda dapat menghindari membangun (dan merusak) bingkai tumpukan lain.
Baik fungsi yang dihasilkan oleh parsial maupun lambdas tidak memiliki dokumen secara default (meskipun Anda dapat mengatur string doc untuk objek apa pun melalui
__doc__
).Anda dapat menemukan rincian lebih lanjut di blog ini: Aplikasi Fungsi Sebagian dengan Python
sumber
Saya memahami maksud tercepat dalam contoh ketiga.
Ketika saya mengurai lambdas, saya mengharapkan lebih banyak kompleksitas / keanehan daripada yang ditawarkan oleh perpustakaan standar secara langsung.
Anda juga akan melihat bahwa contoh ketiga adalah satu-satunya yang tidak bergantung pada tanda tangan lengkap dari
sum2
; sehingga membuatnya sedikit lebih longgar digabungkan.sumber
functools.partial
panggilan, sedangkan lambda jelas.