Saya kebanyakan menggunakan fungsi lambda tetapi terkadang menggunakan fungsi bersarang yang tampaknya memberikan perilaku yang sama.
Berikut adalah beberapa contoh sepele di mana mereka secara fungsional melakukan hal yang sama jika keduanya ditemukan dalam fungsi lain:
Fungsi Lambda
>>> a = lambda x : 1 + x
>>> a(5)
6
Fungsi bersarang
>>> def b(x): return 1 + x
>>> b(5)
6
Apakah ada keuntungan menggunakan salah satu dari yang lain? (Kinerja? Keterbacaan? Keterbatasan? Konsistensi? Dll.)
Apakah itu penting? Jika tidak maka apakah itu melanggar prinsip Pythonic:
Seharusnya ada satu — dan sebaiknya hanya satu — cara yang jelas untuk melakukannya .
lambda
, tapi saya tidak setuju bahwa ini "sangat jarang", ini umum untuk fungsi tombolsorted
atauitertools.groupby
dll., Misalnyasorted(['a1', 'b0'], key= lambda x: int(x[1]))
Secara praktis, bagi saya ada dua perbedaan:
Yang pertama adalah tentang apa yang mereka lakukan dan apa yang mereka hasilkan:
def adalah kata kunci yang tidak mengembalikan apa pun dan membuat 'nama' di namespace lokal.
lambda adalah kata kunci yang mengembalikan objek fungsi dan tidak membuat 'nama' di namespace lokal.
Karenanya, jika Anda perlu memanggil fungsi yang mengambil objek fungsi, satu-satunya cara untuk melakukannya dalam satu baris kode python adalah dengan lambda. Tidak ada padanan dengan def.
Dalam beberapa kerangka kerja ini sebenarnya cukup umum; misalnya, saya sering menggunakan Twisted , dan melakukan sesuatu seperti
cukup umum, dan lebih ringkas dengan lambda.
Perbedaan kedua adalah tentang fungsi sebenarnya yang boleh dilakukan.
Sebagai contoh,
bekerja seperti yang diharapkan, sementara
adalah SyntaxError.
Tentu saja, ada beberapa solusi - ganti
print
dengansys.stdout.write
, atauimport
dengan__import__
. Tetapi biasanya Anda lebih baik menggunakan fungsi dalam kasus itu.sumber
Dalam wawancara ini, Guido van Rossum mengatakan dia berharap dia tidak membiarkan 'lambda' menjadi Python:
IMHO, Iambdas kadang-kadang bisa nyaman, tetapi biasanya nyaman dengan mengorbankan kesiapan. Bisakah Anda memberi tahu saya apa fungsinya:
Saya menulisnya, dan butuh waktu satu menit untuk mengetahuinya. Ini dari Project Euler - saya tidak akan mengatakan masalah mana karena saya benci spoiler, tetapi berjalan dalam 0,124 detik :)
sumber
lambda
tidak dihapus di 3.0 adalah hal yang dekat, dan bahwa Guido tidak berjuang untuk mempertahankannya.Untuk n = 1000 inilah beberapa waktu untuk memanggil fungsi vs lambda:
sumber
Performa:
Membuat fungsi dengan
lambda
ini sedikit lebih cepat daripada menciptakan dengandef
. Perbedaannya adalah karenadef
membuat entri nama di tabel penduduk setempat. Fungsi yang dihasilkan memiliki kecepatan eksekusi yang sama.Keterbacaan:
Fungsi Lambda agak kurang dapat dibaca oleh sebagian besar pengguna Python, tetapi juga jauh lebih ringkas dalam beberapa keadaan. Pertimbangkan untuk mengubah dari menggunakan rutinitas non-fungsional ke fungsional:
Seperti yang Anda lihat,
lambda
versi ini lebih pendek dan "lebih mudah" dalam arti bahwa Anda hanya perlu menambahkanlambda v:
ke versi non-fungsional asli untuk mengubahnya ke versi fungsional. Ini juga jauh lebih ringkas. Tapi ingat, banyak pengguna Python akan bingung dengan sintaks lambda, jadi apa yang Anda kehilangan panjangnya dan kompleksitas sebenarnya mungkin diperoleh kembali dalam kebingungan dari sesama pembuat kode.Batasan:
lambda
fungsi hanya dapat digunakan sekali, kecuali ditetapkan ke nama variabel.lambda
fungsi yang ditetapkan ke nama variabel tidak memiliki keunggulan dibandingkandef
fungsi.lambda
fungsi bisa sulit atau tidak mungkin untuk dibuat acar.def
nama fungsi harus dipilih dengan cermat agar cukup deskriptif dan unik atau setidaknya tidak digunakan dalam cakupan.Konsistensi:
Python kebanyakan menghindari konvensi pemrograman fungsional demi semantik prosedural dan objektif yang lebih sederhana. The
lambda
Operator berdiri di kontras dengan bias ini. Selain itu, sebagai alternatif dari yang sudah lazimdef
,lambda
fungsi menambahkan keragaman pada sintaks Anda. Beberapa akan menganggap itu kurang konsisten.Fungsi yang sudah ada sebelumnya:
Seperti dicatat oleh orang lain, banyak kegunaan
lambda
di lapangan dapat diganti oleh anggotaoperator
atau modul lain. Misalnya:Menggunakan fungsi yang sudah ada sebelumnya dapat membuat kode lebih mudah dibaca dalam banyak kasus.
Prinsip Pythonic: “Harus ada satu — dan sebaiknya hanya satu — cara yang jelas untuk melakukannya”
Itu serupa dengan doktrin sumber tunggal kebenaran . Sayangnya, prinsip satu-cara-untuk-melakukannya selalu lebih merupakan aspirasi yang menyedihkan untuk Python, daripada prinsip pembimbing yang sebenarnya. Pertimbangkan pemahaman array yang sangat kuat dengan Python. Mereka secara fungsional setara dengan fungsi
map
danfilter
:lambda
dandef
sama.Ini masalah opini, tapi saya akan mengatakan bahwa apapun dalam bahasa Python yang ditujukan untuk penggunaan umum yang jelas tidak merusak apapun sudah cukup "Pythonic".
sumber
Ada satu keuntungan menggunakan lambda dibandingkan fungsi reguler: fungsi tersebut dibuat dalam ekspresi.
Ada beberapa kekurangan:
'<lambda>'
)Keduanya juga merupakan jenis objek yang sama. Untuk alasan tersebut, saya biasanya lebih suka membuat fungsi dengan
def
kata kunci daripada dengan lambda.Poin pertama - mereka adalah tipe objek yang sama
Sebuah lambda menghasilkan tipe objek yang sama dengan fungsi biasa
Karena lambda adalah fungsi, mereka adalah objek kelas satu.
Baik lambda dan fungsi:
Tetapi lambda, secara default, kehilangan beberapa hal yang didapat fungsi melalui sintaks definisi fungsi penuh.
Lamba
__name__
adalah'<lambda>'
Lambda adalah fungsi anonim, jadi mereka tidak tahu namanya sendiri.
Jadi lambda's tidak dapat dicari secara terprogram di namespace mereka.
Ini membatasi hal-hal tertentu. Misalnya,
foo
dapat dicari dengan kode serial, sementaral
tidak bisa:Kita dapat mencari dengan
foo
baik - karena mengetahui namanya sendiri:Lambdas tidak memiliki anotasi dan tidak ada docstring
Pada dasarnya, lambda tidak didokumentasikan. Mari menulis ulang
foo
agar terdokumentasi lebih baik:Sekarang, foo memiliki dokumentasi:
Padahal, kami tidak memiliki mekanisme yang sama untuk memberikan informasi yang sama ke lambda:
Tapi kita bisa meretasnya:
Tapi mungkin ada beberapa kesalahan yang mengacaukan hasil bantuan.
Lambdas hanya bisa mengembalikan ekspresi
Lambdas tidak bisa mengembalikan pernyataan kompleks, hanya ekspresi.
Ekspresi memang bisa jadi agak rumit, dan jika Anda berusaha sangat keras, Anda mungkin dapat mencapai hal yang sama dengan lambda, tetapi kerumitan yang ditambahkan lebih merugikan penulisan kode yang jelas.
Kami menggunakan Python untuk kejelasan dan pemeliharaan. Penggunaan lambda yang berlebihan bisa melawan itu.
Satu- satunya keuntungan lambda: bisa dibuat dalam satu ekspresi
Ini adalah satu-satunya kemungkinan kenaikan. Karena Anda dapat membuat lambda dengan ekspresi, Anda dapat membuatnya di dalam pemanggilan fungsi.
Membuat fungsi di dalam panggilan fungsi menghindari pencarian nama (murah) versus yang dibuat di tempat lain.
Namun, karena Python dievaluasi secara ketat, tidak ada perolehan performa lain selain menghindari pencarian nama.
Untuk ekspresi yang sangat sederhana, saya mungkin memilih lambda.
Saya juga cenderung menggunakan lambda saat melakukan Python interaktif, untuk menghindari banyak baris saat seseorang melakukannya. Saya menggunakan jenis format kode berikut ketika saya ingin meneruskan argumen ke konstruktor saat memanggil
timeit.repeat
:Dan sekarang:
Saya percaya sedikit perbedaan waktu di atas dapat dikaitkan dengan pencarian nama di
return_nullary_function
- perhatikan bahwa itu sangat dapat diabaikan.Kesimpulan
Lambda bagus untuk situasi informal di mana Anda ingin meminimalkan baris kode untuk membuat titik tunggal.
Lambda buruk untuk situasi yang lebih formal di mana Anda memerlukan kejelasan untuk editor kode yang akan datang nanti, terutama dalam kasus di mana mereka tidak sepele.
Kami tahu kami harus memberikan nama yang baik pada objek kami. Bagaimana kita bisa melakukannya jika objek tidak memiliki nama?
Untuk semua alasan ini, saya biasanya lebih suka membuat fungsi dengan
def
daripada denganlambda
.sumber
Saya setuju dengan saran nosklo: jika Anda perlu memberi nama fungsi, gunakan
def
. Saya memesanlambda
fungsi untuk kasus di mana saya hanya meneruskan cuplikan singkat kode ke fungsi lain, misalnya:sumber
Meskipun setuju dengan jawaban lain, terkadang lebih mudah dibaca. Berikut ini adalah contoh di mana
lambda
sangat berguna, dalam kasus penggunaan saya terus menghadapi suatu N dimensidefaultdict
.Berikut contohnya:
Saya merasa lebih mudah dibaca daripada membuat
def
untuk dimensi kedua. Ini bahkan lebih signifikan untuk dimensi yang lebih tinggi.sumber
from functools import partial; defaultdict(partial(defaultdict, list))
. Tetapkan parsial ke sebuah nama jika Anda ingin menggunakannya lebih dari sekali. Tetapi, jika Anda terus menemukan konstruksi ini, itu berarti Anda tidak KERING. Faktorkan menjadi pustaka utilitas. Anda dapat menggunakan konstruksi ini untuk membuat defaultdict n-dimensi arbiter menggunakan functools lain (atau loop atau rekursi).Penggunaan utama lambda selalu untuk fungsi callback sederhana, dan untuk map, reduce, filter, yang memerlukan fungsi sebagai argumen. Dengan pemahaman daftar menjadi norma, dan tambahan diperbolehkan jika seperti:
Sulit membayangkan kasus nyata penggunaan lambda dalam penggunaan sehari-hari. Akibatnya, menurut saya, hindari lambda dan buat fungsi bersarang.
sumber
Batasan penting lambda adalah bahwa lambda tidak dapat berisi apa pun selain ekspresi. Hampir tidak mungkin bagi ekspresi lambda untuk menghasilkan apa pun selain efek samping yang sepele, karena tidak dapat memiliki tubuh yang sekaya
def
fungsi 'ed.Karena itu, Lua memengaruhi gaya pemrograman saya terhadap penggunaan fungsi anonim secara ekstensif, dan saya mengotori kode saya dengan mereka. Selain itu, saya cenderung berpikir tentang map / reduce sebagai operator abstrak dengan cara yang tidak saya anggap sebagai pemahaman daftar atau generator, hampir seperti jika saya menunda keputusan implementasi secara eksplisit dengan menggunakan operator tersebut.
Sunting: Ini adalah pertanyaan yang cukup lama, dan pendapat saya tentang masalah ini agak berubah.
Pertama, saya sangat bias terhadap penempatan
lambda
ekspresi ke variabel; karena python memiliki sintaks khusus hanya untuk itu (petunjuk,def
). Selain itu, banyak penggunaan lambda, meskipun tidak mendapatkan nama, memiliki implementasi yang ditentukan sebelumnya (dan lebih efisien). Misalnya, contoh yang dimaksud dapat disingkat menjadi hanya(1).__add__
, tanpa perlu membungkusnya denganlambda
ataudef
. Banyak kegunaan umum lainnya yang dapat dipenuhi dengan beberapa kombinasi darioperator
,itertools
danfunctools
modul.sumber
(1).__add__
- memanggil metode dunder secara langsung seharusnya hampir tidak pernah terjadi. Seribulambda
detik untuk setiap panggilan darurat langsung.(1).__add__
agak tidak umum, tetapi saya tidak akan mendekati "seharusnya". tanpa ragu, saya menemukan yang pertama jauh lebih mudah dibacalambda x: 1 + x
. Jika kita memiliki sesuatu yang lebih mirip dengan notasi irisan haskell,(1+)
itu akan bagus, tapi kita harus puas dengan apa yang secara semantik persisnya, nama metode dunder.Mempertimbangkan contoh sederhana,
sumber
Jika Anda hanya akan menetapkan lambda ke variabel dalam lingkup lokal, Anda juga dapat menggunakan def karena lebih mudah dibaca dan dapat diperluas dengan lebih mudah di masa mendatang:
atau
sumber
from operator import pow;map(pow, someList)
dan(a**b for a,b in someList)
bahkan lebih mudah dibaca.Satu kegunaan lambda yang saya temukan ... ada dalam pesan debug.
Karena lambda dapat dievaluasi dengan malas, Anda dapat memiliki kode seperti ini:
daripada mungkin mahal:
yang memproses string format meskipun panggilan debug tidak menghasilkan keluaran karena tingkat logging saat ini.
Tentu saja agar dapat bekerja seperti yang dijelaskan modul logging yang digunakan harus mendukung lambda sebagai "parameter malas" (seperti modul logging saya).
Ide yang sama dapat diterapkan pada kasus evaluasi malas lainnya untuk pembuatan nilai konten sesuai permintaan.
Misalnya operator terner adat ini:
dari pada:
dengan lambda hanya ekspresi yang dipilih oleh kondisi yang akan dievaluasi, tanpa lambda keduanya akan dievaluasi.
Tentu saja Anda bisa menggunakan fungsi sebagai ganti lambda, tetapi untuk ekspresi pendek lambda adalah (c) lebih ramping.
sumber
logging
sudah memiliki format lazy:log.debug("this is my message: %r", some_data)
hanya akan diformat jika / jika pesan diminta.some_data
dapat berupa ekspresi atau pemanggilan fungsi / metode yang mahal.Saya setuju dengan nosklo. Ngomong-ngomong, bahkan dengan sekali pakai, buang fungsi, sebagian besar waktu Anda hanya ingin menggunakan sesuatu dari modul operator.
TELUR:
Anda memiliki fungsi dengan tanda tangan ini: myFunction (data, fungsi panggilan balik).
Anda ingin melewatkan fungsi yang menambahkan 2 elemen.
Menggunakan lambda:
Cara pythonic:
Atau tentu saja ini adalah contoh sederhana, tetapi ada banyak hal yang disediakan oleh modul operator, termasuk item setter / getter untuk list dan dict. Benar-benar keren.
sumber
Perbedaan utama adalah Anda tidak dapat menggunakan
def
fungsi sebaris, yang menurut saya kasus penggunaan yang paling nyaman untuk suatulambda
fungsi. Misalnya saat mengurutkan daftar objek:Oleh karena itu, saya menyarankan agar penggunaan lambda untuk operasi sepele semacam ini, yang juga tidak benar-benar mendapatkan keuntungan dari dokumentasi otomatis yang disediakan dengan menamai fungsi tersebut.
sumber
lambda berguna untuk menghasilkan fungsi baru:
sumber