Mengapa Python lambdas bermanfaat? [Tutup]

929

Saya mencoba mencari tahu Python lambdas. Apakah lambda salah satu item bahasa "menarik" yang dalam kehidupan nyata harus dilupakan?

Saya yakin ada beberapa kasus tepi di mana mungkin diperlukan, tetapi mengingat ketidakjelasan itu, potensi itu didefinisikan ulang dalam rilis mendatang (asumsi saya berdasarkan berbagai definisi itu) dan kejelasan pengkodean yang dikurangi - jika dihindari?

Ini mengingatkan saya pada overflow (buffer overflow) dari tipe C - menunjuk ke variabel teratas dan overloading untuk mengatur nilai field lainnya. Rasanya seperti semacam kecakapan memainkan pertunjukan teknisi tapi pemeliharaan mimpi buruk coder.

meade
sumber
261
+1 Pertanyaan bagus - asumsi buruk (ketidakjelasan lambda) =) Cobalah untuk tidak menghakimi teknik pemrograman. Mengevaluasi mereka, dan menambahkannya ke perangkat mental Anda. Jika Anda tidak menyukainya, jangan menggunakannya, dan bersiaplah untuk membahasnya secara logis tanpa menjadi religius.
Kieveli
41
Aturan Haskell! Fungsi Lambda memberi Anda daya ekspresif dan abstraksi.
Jonathan Barbero
11
@ JAL Belum lagi LISP ...
ApproachingDarknessFish
8
@ApproachingDarknessFish "Ah, itu Parenthesis ayahmu. Senjata yang lebih beradab dari zaman yang lebih beradab." - Obi Lisp Kenobi
Fields

Jawaban:

1009

Apakah Anda berbicara tentang fungsi lambda ? Suka

lambda x: x**2 + 2*x - 5

Hal-hal itu sebenarnya cukup bermanfaat. Python mendukung gaya pemrograman yang disebut pemrograman fungsional di mana Anda dapat meneruskan fungsi ke fungsi lain untuk melakukan sesuatu. Contoh:

mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])

set mult3ke [3, 6, 9], elemen-elemen dari daftar asli yang merupakan kelipatan dari 3. Ini lebih pendek (dan, orang bisa berpendapat, lebih jelas) daripada

def filterfunc(x):
    return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])

Tentu saja, dalam kasus khusus ini, Anda dapat melakukan hal yang sama dengan pemahaman daftar:

mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]

(atau bahkan sama range(3,10,3)), tetapi ada banyak kasus penggunaan lain yang lebih canggih di mana Anda tidak dapat menggunakan pemahaman daftar dan fungsi lambda mungkin merupakan cara terpendek untuk menulis sesuatu.

  • Mengembalikan fungsi dari fungsi lain

    >>> def transform(n):
    ...     return lambda x: x + n
    ...
    >>> f = transform(3)
    >>> f(4)
    7

    Ini sering digunakan untuk membuat pembungkus fungsi, seperti dekorator Python.

  • Menggabungkan elemen dari urutan yang dapat diubah dengan reduce()

    >>> reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])
    '1, 2, 3, 4, 5, 6, 7, 8, 9'
  • Menyortir dengan tombol alternatif

    >>> sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))
    [5, 4, 6, 3, 7, 2, 8, 1, 9]

Saya menggunakan fungsi lambda secara teratur. Butuh beberapa saat bagi saya untuk terbiasa dengan mereka, tetapi akhirnya saya mengerti bahwa mereka adalah bagian yang sangat berharga dari bahasa tersebut.

David Z
sumber
26
Suka contohnya, sangat mudah dimengerti. Tetapi untuk mengurangi bagian. Jika saya harus mengimplementasikan fitur ini. Saya akan melakukan','.join(str(x) for x in [1,2,3,4,5,6,7,8,9])
etlds
3
BTW jika Anda menjalankan ini pada Python3 Anda perlu memanggil daftar pada hasil filter untuk melihat nilai aktual, juga Anda perlu mengimpor pengurangan dari functools
Gerard
Apakah kita yakin tentang definisi "pemrograman fungsional" di atas? Itu datang sedikit membingungkan saya.
stdout
3
Saya pikir poin kuncinya adalah bahwa lambdafungsi dapat anonim (seperti yang ada dalam semua contoh Anda). Jika Anda menetapkan lambdafungsi untuk apa-apa maka Anda melakukannya salah dan harus menggunakan defsebaliknya
Chris_Rands
1
@ zgulser Ini bukan definisi, itu hanya pernyataan tentang sesuatu yang memungkinkan Anda melakukan pemrograman fungsional.
David Z
377

lambdahanyalah cara mewah untuk mengatakan function. Selain namanya, tidak ada yang tidak jelas, mengintimidasi atau samar tentang hal itu. Ketika Anda membaca baris berikut, gantikan lambdadengan functiondalam pikiran Anda:

>>> f = lambda x: x + 1
>>> f(3)
4

Itu hanya mendefinisikan fungsi x. Beberapa bahasa lain, seperti R, mengatakannya secara eksplisit:

> f = function(x) { x + 1 }
> f(3)
4

Kamu melihat? Ini adalah salah satu hal paling alami untuk dilakukan dalam pemrograman.

pengguna251650
sumber
36
Ini adalah deskripsi yang bagus untuk mereka yang berasal dari latar belakang non-pemrograman (yaitu: ilmu pasti) yang membuat makna lambda sangat sederhana untuk dipahami. Terima kasih!
Gabriel
10
Raymond Hettinger menyesali nama itu dalam salah satu ceramahnya dan mengatakan bahwa semua kebingungan dapat dihindari dengan menamakannya 'berfungsi' alih-alih 'lambda'. :-)
ankush981
10
ganti lambdadengan functiondi pikiran Anda dan tambahkan returnsebelum ekspresi terakhir
Ciprian Tomoiagă
4
@AaronMcMillin Coba type(lambda x: 3). lambdaekspresi dan defpernyataan keduanya menghasilkan functionobjek; hanya sintaks lambdaekspresi yang membatasi instance mana yang dapat dihasilkannya.
chepner
6
@AaronMcMillin Anda kehilangan poin saya. Hanya karena Anda tidak dapat mendefinisikan setiap fungsi dengan lambdaekspresi bukan berarti hasil dari lambdaekspresi bukanlah fungsi.
chepner
107

Ringkasan dua baris:

  1. Penutupan : Sangat bermanfaat. Pelajari mereka, gunakan, cintai.
  2. lambdaKata kunci Python : tidak perlu, terkadang berguna. Jika Anda menemukan diri Anda melakukan sesuatu yang jauh rumit dengannya, simpan dan tentukan fungsi yang sebenarnya.
John Fouhy
sumber
72

Lambda adalah bagian dari mekanisme abstraksi yang sangat penting yang berkaitan dengan fungsi-fungsi tingkat tinggi. Untuk mendapatkan pemahaman yang benar tentang nilainya, silakan lihat pelajaran berkualitas tinggi dari Abelson dan Sussman , dan baca buku SICP

Ini adalah masalah yang relevan dalam bisnis perangkat lunak modern, dan menjadi semakin populer.

egaga
sumber
1
Ekspresi Lambda menjadi populer dalam bahasa lain (seperti C #) juga. Mereka tidak ke mana-mana. Membaca pada penutupan akan menjadi latihan yang berguna untuk memahami Lambdas. Penutupan membuat banyak sihir pengkodean mungkin dalam kerangka kerja seperti jQuery.
Dan Esparza
3
Jangan bingung lambdafungsi s dan kelas satu. Python memiliki pernyataan yang sangat terbatas lambda, tetapi sepenuhnya fungsi kelas satu. Satu-satunya perbedaan yang dibuatnya adalah Anda harus memberi nama fungsi yang ingin Anda sampaikan.
Gareth Latty
59

lambdas sangat berguna dalam pemrograman GUI. Misalnya, katakanlah Anda sedang membuat grup tombol dan Anda ingin menggunakan satu panggilan balik paramaterized daripada satu panggilan balik unik per tombol. Lambda memungkinkan Anda melakukannya dengan mudah:

for value in ["one","two","three"]:
    b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
    b.pack()

(Catatan: meskipun pertanyaan ini khusus ditanyakan lambda, Anda juga dapat menggunakan functools.partial untuk mendapatkan jenis hasil yang sama)

Alternatifnya adalah membuat panggilan balik terpisah untuk setiap tombol yang dapat menyebabkan kode digandakan.

Bryan Oakley
sumber
1
Inilah sebabnya saya mencari lambda, tetapi mengapa ini berhasil, bagi saya kelihatannya sama persis dengan hanya memanggil fungsi langsung ( stackoverflow.com/questions/3704568/… ). Mungkin sudah terlambat, itu berhasil, tetapi mengapa itu berhasil?
Rqomey
5
@Rqomey: perbedaannya adalah bahwa dalam contoh valueini didefinisikan dalam satu lingkaran; dalam contoh lain parameter selalu hanya memiliki satu nilai. Ketika Anda menambahkan sesuatu seperti arg=value, Anda melampirkan nilai saat ini ke callback. Tanpa itu, Anda mengikat referensi ke variabel dalam panggilan balik. Referensi akan selalu berisi nilai akhir variabel, karena panggilan balik terjadi beberapa saat setelah loop telah selesai berjalan.
Bryan Oakley
1
Saya baru saja bekerja kemarin, saya jujur ​​tidak percaya betapa bergunanya itu ... Saya dapat membangun menu dari satu untuk loop dan file csv untuk konfigurasi. Hal yang sangat berguna.
Rqomey
1
Perhatikan keberadaannya functools.partial()yang memungkinkan Anda melakukan ini dengan sedikit cacat (dan tanpa lambda).
Gareth Latty
2
partial(my_callback, value)vs lambda arg=value: my_callback(arg)- lambda memiliki lebih banyak cruft (tugas untuk arg dan kemudian penggunaan) dan kurang jelas apa maksudnya (Anda bisa melakukan sesuatu yang agak berbeda di lambda). Impor tidak benar-benar masalah (Anda masih memiliki tumpukan dan itu sekali per file). Kode paling baik dinilai berdasarkan seberapa baik ia membaca, dan partial()jauh lebih mudah dibaca daripada lambda.
Gareth Latty
58

Saya ragu lambda akan pergi. Lihat posting Guido tentang akhirnya menyerah mencoba menghapusnya. Juga lihat garis besar konflik .

Anda dapat memeriksa posting ini untuk mengetahui lebih banyak tentang sejarah tentang kesepakatan di balik fitur fungsional Python: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

Anehnya, peta, filter, dan mengurangi fungsi yang awalnya memotivasi pengenalan lambda dan fitur fungsional lainnya sebagian besar telah digantikan oleh daftar pemahaman dan ekspresi generator. Bahkan, fungsi pengurangan telah dihapus dari daftar fungsi builtin di Python 3.0. (Namun, tidak perlu mengirim keluhan tentang penghapusan lambda, peta, atau filter: mereka tetap ada. :-)

Dua sen saya sendiri: Jarang adalah nilai lambda sejauh kejelasannya. Secara umum ada solusi yang lebih jelas yang tidak termasuk lambda.

rhettg
sumber
2
perhatikan bahwa pengurangan masih dapat diimpor dalam Python 3.0. Jika Anda BENAR-BENAR menginginkannya, Anda masih dapat memilikinya.
Paweł Polewicz
Saya pikir upaya Guido lebih tentang sintaksis. Orang ini juga berpikir bahwa: cackhanded.com/blog/post/2008/01/24/…
leewz
38

Dalam Python, lambdahanyalah cara mendefinisikan fungsi inline,

a = lambda x: x + 1
print a(1)

dan..

def a(x): return x + 1
print a(1)

..adalah persis sama.

Tidak ada yang dapat Anda lakukan dengan lambda yang tidak dapat Anda lakukan dengan fungsi biasa — dalam fungsi Python adalah objek seperti yang lainnya, dan lambdas hanya mendefinisikan fungsi:

>>> a = lambda x: x + 1
>>> type(a)
<type 'function'>

Jujur saya pikir itu lambda kata kunci itu berlebihan di Python — saya tidak pernah memiliki kebutuhan untuk menggunakannya (atau melihat yang digunakan di mana fungsi biasa, pemahaman daftar atau salah satu dari banyak fungsi builtin bisa lebih baik digunakan sebagai gantinya)

Untuk contoh yang benar-benar acak, dari artikel "lambda Python rusak!" :

Untuk melihat bagaimana lambda rusak, coba buat daftar fungsi di fs=[f0,...,f9]mana fi(n)=i+n. Percobaan pertama:

>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13

Saya berpendapat, bahkan jika itu berhasil, itu mengerikan dan "unpythonic", fungsi yang sama dapat ditulis dalam banyak cara lain, misalnya:

>>> n = 4
>>> [i + n for i in range(10)]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

Ya, itu tidak sama, tetapi saya belum pernah melihat penyebab di mana menghasilkan sekelompok fungsi lambda dalam daftar telah diperlukan. Mungkin masuk akal dalam bahasa lain, tetapi Python bukan Haskell (atau Lisp, atau ...)

Harap dicatat bahwa kami dapat menggunakan lambda dan masih mencapai hasil yang diinginkan dengan cara ini:

>>> fs = [(lambda n,i=i: i + n) for i in range(10)]
>>> fs[3](4)
7

Edit:

Ada beberapa kasus di mana lambda berguna, misalnya sering nyaman ketika menghubungkan sinyal dalam aplikasi PyQt, seperti ini:

w = PyQt4.QtGui.QLineEdit()
w.textChanged.connect(lambda event: dothing())

Melakukan sesuatu w.textChanged.connect(dothing)akan memanggil dothingmetode dengan eventargumen tambahan dan menyebabkan kesalahan. Menggunakan lambda berarti kita dapat dengan mudah menjatuhkan argumen tanpa harus mendefinisikan fungsi pembungkus.

dbr
sumber
2
Argumen "lambda Anda rusak" rusak, karena aturan pelingkupan variabel python bekerja seperti itu, titik. Anda akan digigit dengan cara yang sama jika Anda membuat penutupan di dalam untuk-loop.
Antti Haapala
1
lambda hanyalah cara python untuk menyediakan pengguna dengan fungsi "anonim", seperti yang dimiliki banyak bahasa lain (misalnya, javascript).
Stefan Gruenwald
1
Lambda dan fungsi ayang Anda tetapkan tidak persis sama. :) Mereka berbeda berdasarkan __name__bidang setidaknya ...
nperson325681
1
Ini berfungsi lebih dari sekadar fungsi sebaris.
kta
Argumen Anda tentang "mungkin masuk akal dalam bahasa lain" itu aneh. Entah ada kualitas intrinsik dari lambda, atau tidak.
Titou
31

Saya menemukan lambda berguna untuk daftar fungsi yang melakukan hal yang sama, tetapi untuk keadaan yang berbeda.

Seperti aturan jamak Mozilla :

plural_rules = [
    lambda n: 'all',
    lambda n: 'singular' if n == 1 else 'plural',
    lambda n: 'singular' if 0 <= n <= 1 else 'plural',
    ...
]
# Call plural rule #1 with argument 4 to find out which sentence form to use.
plural_rule[1](4) # returns 'plural'

Jika Anda harus mendefinisikan fungsi untuk semua yang Anda akan menjadi gila pada akhir itu.
Juga, itu tidak akan bagus dengan nama fungsi seperti plural_rule_1, plural_rule_2, dll Dan Anda akan perlu untuk eval()itu ketika Anda tergantung pada fungsi variabel id.

Tor Valamo
sumber
1
Ini terlihat mirip dengan pertemuan singkat yang saya miliki sejauh ini di F # dengan pencocokan pola dan opsi. Apakah Anda memiliki info lebih lanjut tentang cara menggunakan sintaks ini?
Ken
26

Cukup banyak hal yang dapat Anda lakukan lambda dapat dilakukan dengan fungsi atau daftar dan ekspresi generator.

Akibatnya, untuk sebagian besar Anda harus hanya salah satu dari mereka yang pada dasarnya situasi apa pun (kecuali mungkin untuk kode awal yang ditulis dalam interpreter interaktif).

Aaron Maenpaa
sumber
3
"Untuk sebagian besar, Anda harus hanya salah satu dari mereka yang pada dasarnya ada situasi" Periode. Mengetik lambda di penerjemah bahkan tidak membantu.
S.Lott
11
@ Javier Saya setuju dengan Anda jika Anda berbicara tentang "lambda" konsep; namun, jika kita berbicara tentang "lambda" kata kunci python maka: 1) fungsi yang dinamai lebih cepat dan dapat melakukan lebih banyak (pernyataan + ekspresi) hampir di mana saja Anda akan menggunakan lambdas (peta + filter) Anda hanya dapat menghasilkan ekspresi atau daftar pemahaman yang lebih berkinerja dan ringkas. Saya tidak mengatakan bahwa fungsi kelas pertama tidak keren, hanya saja kata kunci "lambda" dalam python tidak sebagus hanya menggunakan fungsi bernama, itu saja.
Aaron Maenpaa
3
lambda telah sangat diperlukan bagi saya untuk digunakan dengan fungsi yang mengambil argumen callback seperti kunci = argumen untuk mengurutkan () dan diurutkan ()
Rick Copeland
19
@Rick Saya tidak meragukannya, tetapi kenyataannya adalah jika ketika Anda melihat "lambda" dan Anda berpikir "zohmygod lambda" dan mulai menulis kode skema dengan python, Anda akan dengan masam kecewa dengan keterbatasan ekspresi lambda python. Di sisi lain, jika Anda mulai berpikir untuk diri sendiri "Akankah daftar pemahaman berfungsi? Tidak. Apakah yang saya perlukan manfaat dari menjadi fungsi bernama? Tidak. Oke baik: diurutkan (xs, key = lambda x: x.name, x.tinggi) ", Anda mungkin akan menggunakan lambda beberapa kali.
Aaron Maenpaa
4
+1: Saya tidak bisa cukup menekankan bahwa ketika seseorang menggunakan lambda satu menggunakan fungsi tanpa nama . Dan nama memang memiliki nilai tambah intelektual yang berharga .
Stephane Rolland
19

Saya telah menggunakan Python selama beberapa tahun dan saya tidak pernah menjalankan kasus dimana saya membutuhkan lambda. Sungguh, seperti yang dinyatakan dalam tutorial , itu hanya untuk gula sintaksis.

Matt Schmidt
sumber
8
Mereka sangat berguna ketika mengembangkan GUI menggunakan python. Seringkali, widget membutuhkan referensi ke suatu fungsi. Jika Anda membutuhkan widget untuk memanggil suatu fungsi dan menyampaikan argumen, lambda adalah cara yang sangat mudah untuk melakukannya.
Bryan Oakley
1
Apa keuntungan dari melewati beberapa argumen ke dalam fungsi? func_name (a, b): mengembalikan a + b daripada menggunakan lambda
dter
2
itu tidak diperlukan tetapi membantu untuk menulis kode yang lebih pendek dan lebih mudah dibaca dalam banyak kasus, khususnya. dalam bahasa verbose seperti Java atau C ++
phuclv
17

Saya tidak dapat berbicara dengan implementasi lambda dari python, tetapi secara umum fungsi lambda sangat berguna. Mereka adalah teknik inti (bahkan mungkin THE teknik) pemrograman fungsional, dan mereka juga sangat berguna dalam program berorientasi objek. Untuk jenis masalah tertentu, mereka adalah solusi terbaik, jadi tentunya tidak boleh dilupakan!

Saya sarankan Anda membaca tentang penutupan dan fungsi peta (yang menghubungkan ke python docs, tetapi ada di hampir setiap bahasa yang mendukung konstruksi fungsional) untuk melihat mengapa itu berguna.

rmeador
sumber
3
Hal itu bisa dilakukan tanpa lambda. Ini hanya masalah besar.
Brian
17

Fungsi Lambda ini adalah cara non-birokratis untuk membuat fungsi.

Itu dia. Sebagai contoh, mari kita anggap Anda memiliki fungsi utama dan perlu menguadratkan nilai. Mari kita lihat cara tradisional dan cara lambda untuk melakukan ini:

Cara tradisional:

def main():
...
...
y = square(some_number)
...
return something

def square(x):
    return x**2

Cara lambda:

def main():
...
square = lambda x: x**2
y = square(some_number)
return something

Lihat perbedaannya?

Fungsi Lambda berjalan sangat baik dengan daftar, seperti daftar pemahaman atau peta. Bahkan, pemahaman daftar itu adalah cara "pythonic" untuk mengekspresikan diri menggunakan lambda. Ex:

>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]

Mari kita lihat apa arti setiap elemen dari sintaks:

[]: "Beri aku daftar"

x ** 2: "menggunakan fungsi yang baru lahir ini"

untuk x in a: "ke dalam setiap elemen dalam"

Itu nyaman, eh? Menciptakan fungsi seperti ini. Mari kita menulis ulang menggunakan lambda:

>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]

Sekarang mari kita gunakan peta, yang merupakan hal yang sama, tetapi lebih netral bahasa. Peta membutuhkan 2 argumen:

(i) satu fungsi

(ii) iterable

Dan memberi Anda daftar di mana setiap elemen itu fungsi yang diterapkan untuk setiap elemen iterable.

Jadi, dengan menggunakan peta kita akan memiliki:

>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)

Jika Anda menguasai lambda dan pemetaan, Anda akan memiliki kekuatan besar untuk memanipulasi data dan secara ringkas. Fungsi Lambda tidak jelas atau menghilangkan kejelasan kode. Jangan membingungkan sesuatu yang keras dengan sesuatu yang baru. Setelah Anda mulai menggunakannya, Anda akan merasa sangat jelas.

Lucas Ribeiro
sumber
13

Salah satu hal yang menyenangkan tentang lambdaitu menurut pendapat saya kurang penting adalah cara menunda evaluasi untuk formulir sederhana sampai nilainya diperlukan. Biarkan saya jelaskan.

Banyak rutin perpustakaan diimplementasikan sehingga memungkinkan parameter tertentu menjadi callable (di antaranya lambda adalah satu). Idenya adalah bahwa nilai aktual akan dihitung hanya pada saat itu akan digunakan (bukan ketika itu disebut). Contoh (dibuat-buat) mungkin bisa membantu menggambarkan hal tersebut. Misalkan Anda memiliki rutinitas yang akan melakukan log cap waktu tertentu. Anda ingin rutin menggunakan waktu saat ini minus 30 menit. Anda akan menyebutnya seperti itu

log_timestamp(datetime.datetime.now() - datetime.timedelta(minutes = 30))

Sekarang anggap fungsi aktual akan dipanggil hanya ketika peristiwa tertentu terjadi dan Anda ingin cap waktu dihitung hanya pada waktu itu. Anda dapat melakukan ini seperti itu

log_timestamp(lambda : datetime.datetime.now() - datetime.timedelta(minutes = 30))

Dengan asumsi log_timestamp kaleng menangani callable seperti ini, itu akan mengevaluasi ini ketika dibutuhkan dan Anda akan mendapatkan cap waktu pada waktu itu.

Tentu saja ada cara alternatif untuk melakukan ini (menggunakan operator modul misalnya) tapi saya harap saya telah menyampaikan intinya.

Perbarui : Di Sini adalah contoh dunia nyata yang sedikit lebih konkret.

Pembaruan 2 : Saya pikir ini adalah contoh dari apa yang disebut thunk .

Noufal Ibrahim
sumber
11

Seperti yang dinyatakan di atas, operator lambda di Python mendefinisikan fungsi anonim, dan dalam fungsi Python adalah penutupan. Penting untuk tidak membingungkan konsep penutupan dengan lambda operator, yang hanya metadon sintaksis bagi mereka.

Ketika saya mulai dengan Python beberapa tahun yang lalu, saya banyak menggunakan lambdas, berpikir mereka keren, bersama dengan daftar pemahaman. Namun, saya menulis dan harus memelihara situs web besar yang ditulis dengan Python, dengan urutan beberapa ribu poin fungsi. Saya telah belajar dari pengalaman bahwa lambdas mungkin baik-baik saja untuk membuat prototipe dengan, tetapi tidak menawarkan apa pun atas fungsi inline (bernama penutupan) kecuali untuk menyimpan beberapa kunci-stoke, atau kadang-kadang tidak.

Pada dasarnya ini bermuara pada beberapa poin:

  • lebih mudah untuk membaca perangkat lunak yang ditulis secara eksplisit menggunakan nama yang bermakna. Penutupan anonim menurut definisi tidak dapat memiliki nama yang bermakna, karena mereka tidak memiliki nama. Keringkasan ini tampaknya, untuk beberapa alasan, juga menginfeksi parameter lambda, maka kita sering melihat contoh seperti lambda x: x + 1
  • lebih mudah untuk menggunakan kembali penutupan yang disebut, karena mereka dapat disebut dengan nama lebih dari sekali, ketika ada nama untuk merujuk mereka.
  • lebih mudah untuk men-debug kode yang menggunakan penutupan bernama daripada lambdas, karena nama akan muncul di tracebacks, dan di sekitar kesalahan.

Itu alasan yang cukup untuk mengumpulkan mereka dan mengubahnya menjadi penutupan bernama. Namun, saya menyimpan dua dendam lain terhadap penutupan anonim.

Dendam pertama hanyalah bahwa mereka hanyalah kata kunci lain yang tidak perlu mengacaukan bahasa.

Dendam kedua lebih dalam dan pada tingkat paradigma, yaitu saya tidak suka bahwa mereka mempromosikan gaya pemrograman fungsional, karena gaya itu kurang fleksibel daripada pesan yang lewat, berorientasi objek atau gaya prosedural, karena kalkulus lambda tidak Turing- selesai (untungnya dengan Python, kita masih bisa keluar dari pembatasan itu bahkan di dalam lambda). Alasan saya merasa lambdas mempromosikan gaya ini adalah:

  • Ada pengembalian tersirat, yaitu mereka sepertinya 'harus' menjadi fungsi.

  • Mereka adalah alternatif mekanisme penyembunyian negara ke mekanisme lain, lebih eksplisit, lebih mudah dibaca, lebih dapat digunakan kembali dan lebih umum: metode.

Saya berusaha keras untuk menulis Python bebas lambda, dan menghapus lambdas saat dilihat. Saya pikir Python akan menjadi bahasa yang sedikit lebih baik tanpa lambda, tapi itu hanya pendapat saya.

Mike A
sumber
1
"... dalam fungsi Python adalah penutupan". Itu tidak benar, seperti yang saya mengerti. Penutupan adalah fungsi, tetapi fungsi tidak selalu merupakan penutupan. Function-> lambda x, y: x + y. Penutupan-> lambda x: lambda y: x + y
0atman
6
"karena kalkulus lambda bukan Turing-lengkap" jelas salah, kalkulus lambda tidak lengkap Turing lengkap, itulah alasan mengapa kalkulus begitu signifikan. Anda bisa mendapatkan rekursi menggunakan Y-combinator,Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
Antti Haapala
Lebih jauh, jika seseorang pergi ke Wikipedia untuk membaca tentang kelengkapan Turing, dikatakan "Contoh klasik adalah kalkulus lambda."
Antti Haapala
Serius - Tidak Turing selesai - jawaban ini membutuhkan pengeditan atau pencabutan yang serius.
Tony Suffolk 66
@ MarcinŁoś Dipilih karena mengikuti KISS. Sebagai perbandingan, buku K&R menyebutkan bahwa meskipun menggunakan penugasan sebagai bagian atau ungkapan yang lebih besar lebih ringkas, buku itu sering kurang dapat dibaca. Tren-tren menggunakan pola pemrograman fungsional basi dan klise. Sudah cukup untuk menyatakan bagaimana mereka dapat digunakan, tetapi terlalu bersemangat untuk menyatakan bahwa mereka sangat penting untuk menjadi pengembang yang kompeten; sepenuhnya subjektif. Argumen ini analog dengan pengembang C ++ yang berpendapat bahwa bahasa tanpa kelas adalah primitif, inferior, dan tidak memadai. "Turing-kelengkapan", argumen-argumennya sangat bagus.
typedeaf
11

Lambdas sebenarnya adalah konstruksi yang sangat kuat yang berasal dari ide-ide dalam pemrograman fungsional, dan itu adalah sesuatu yang tidak akan mudah direvisi, didefinisikan ulang atau dihapus dalam waktu dekat Python. Mereka membantu Anda menulis kode yang lebih kuat karena memungkinkan Anda untuk lulus fungsi sebagai parameter, sehingga gagasan fungsi sebagai warga negara kelas satu.

Lambdas memang cenderung membingungkan, tetapi begitu pemahaman yang kuat diperoleh, Anda dapat menulis kode elegan yang bersih seperti ini:

squared = map(lambda x: x*x, [1, 2, 3, 4, 5])

Baris kode di atas mengembalikan daftar kotak angka-angka dalam daftar. Tentu, Anda juga bisa melakukannya seperti:

def square(x):
    return x*x

squared = map(square, [1, 2, 3, 4, 5])

Jelas kode sebelumnya lebih pendek, dan ini terutama benar jika Anda bermaksud untuk menggunakan fungsi peta (atau fungsi serupa lainnya yang mengambil fungsi sebagai parameter) hanya di satu tempat. Ini juga membuat kode lebih intuitif dan elegan.

Juga, seperti yang disebutkan @David Zaslavsky dalam jawabannya, pemahaman daftar tidak selalu merupakan jalan yang harus ditempuh terutama jika daftar Anda harus mendapatkan nilai dari beberapa cara matematika yang tidak jelas.

Dari sudut pandang yang lebih praktis, salah satu keuntungan terbesar lambda bagi saya baru-baru ini adalah dalam pemrograman GUI dan event-driven. Jika Anda melihat callback di Tkinter, yang mereka ambil sebagai argumen adalah peristiwa yang memicu mereka. Misalnya

def define_bindings(widget):
    widget.bind("<Button-1>", do-something-cool)

def do-something-cool(event):
    #Your code to execute on the event trigger

Sekarang bagaimana jika Anda memiliki beberapa argumen untuk dilewati? Sesuatu yang sederhana seperti melewati 2 argumen untuk menyimpan koordinat klik-mouse. Anda dapat dengan mudah melakukannya seperti ini:

def main():
    # define widgets and other imp stuff
    x, y = None, None
    widget.bind("<Button-1>", lambda event: do-something-cool(x, y))

def do-something-cool(event, x, y):
    x = event.x
    y = event.y
    #Do other cool stuff

Sekarang Anda dapat berargumen bahwa ini dapat dilakukan dengan menggunakan variabel global, tetapi apakah Anda benar-benar ingin memukul kepala Anda khawatir tentang manajemen memori dan kebocoran terutama jika variabel global hanya akan digunakan di satu tempat tertentu? Itu hanya gaya pemrograman yang buruk.

Singkatnya, lambda itu luar biasa dan tidak boleh dianggap remeh. Python lambdas tidak sama dengan LISP lambdas (yang lebih kuat), tetapi Anda benar-benar dapat melakukan banyak hal ajaib dengan mereka.

varagrawal
sumber
Terima kasih. Saya benar-benar tidak mengerti contoh terakhir Anda. Kenapa x dan y didefinisikan dalam keduanya maindan do_something_cool? Apa yang terjadi pada xdan ydalam fungsi? Nilai yang diteruskan tampaknya akan segera ditimpa? Bagaimana fungsi tahu tentang event? Bisakah Anda menambahkan beberapa komentar / penjelasan? Terima kasih
Sanjay Manohar
@SanjayManohar Saya menyampaikan xdan ysebagai argumen untuk do-something-cooldan nilai-nilai mereka sedang diatur dalam fungsi untuk menggambarkan bagaimana Anda dapat menggunakan lambdas untuk melewati argumen di mana tidak ada yang diharapkan. The widget.bindFungsi mengharapkan eventparameter yang mengidentifikasi peristiwa GUI pada itu widget tertentu. Saya merekomendasikan membaca model pemrograman Tkinter untuk kejelasan yang lebih besar.
varagrawal
hmm saya pikir saya mengerti model Tkinter. Tapi masih tidak begitu mengerti - Anda lulus x,ykemudian lakukan x=event.x. Bukankah itu menimpa nilai yang Anda berikan? Dan bagaimana fungsinya mengetahui apa eventitu? Saya tidak melihat di mana Anda meneruskannya ke fungsi. Atau itu metode? Anda juga diizinkan tanda minus dalam nama fungsi?
Sanjay Manohar
SanjayManohar sobat Anda perlu membaca tentang Tkinter dan Python. Tkinter melewatkan objek acara fungsi sebagai tindakan default. Adapun x, y, itu hanya contoh untuk tujuan ilustrasi. Saya mencoba menunjukkan kekuatan lambda, bukan Tkinter. :)
varagrawal
1
OK sekarang saya melihat apa yang Anda maksudkan - Anda ingin fungsi menerima event? dalam hal itu, bukankah lambda Anda harus dibaca lambda event: do_something_cool(event,x,y)?
Sanjay Manohar
8

Lambdas sangat terkait dengan gaya pemrograman fungsional secara umum. Gagasan bahwa Anda dapat memecahkan masalah dengan menerapkan fungsi ke beberapa data, dan menggabungkan hasilnya, adalah apa yang digunakan Google untuk mengimplementasikan sebagian besar algoritmanya.

Program yang ditulis dalam gaya pemrograman fungsional, mudah diparalelkan dan karenanya menjadi semakin penting dengan mesin multi-core modern. Jadi singkatnya, TIDAK Anda tidak boleh melupakan mereka.

Yogi
sumber
7

Selamat pertama yang berhasil menemukan lambda. Menurut pendapat saya ini adalah konstruksi yang sangat kuat untuk bertindak. Tren akhir-akhir ini terhadap bahasa pemrograman fungsional jelas merupakan indikator bahwa hal itu tidak harus dihindari atau akan didefinisikan ulang dalam waktu dekat.

Anda hanya perlu berpikir sedikit berbeda. Saya yakin Anda akan segera menyukainya. Tapi hati-hati jika Anda hanya berurusan dengan python. Karena lambda bukan merupakan penutupan nyata, itu entah bagaimana "rusak": ular sanca lambda rusak

Norbert Hartl
sumber
Lambda Python tidak rusak. Ada dua cara untuk menangani penduduk setempat di lambdas. Keduanya memiliki kelebihan dan kekurangan. Saya pikir pendekatan yang diambil oleh Python (dan C #) mungkin berlawanan dengan yang lebih terbiasa dengan bahasa yang murni fungsional, karena dengan bahasa yang murni fungsional saya tidak berpikir bahwa pendekatan itu bahkan masuk akal.
Brian
Ini memang berlawanan dengan intuisi. Saya bukan programmer python tetapi dalam mencicit smalltalk itu sama dan saya menemukan ini secara teratur. Jadi, bahkan saya akan mempertimbangkan itu "rusak" :)
Norbert Hartl
Tidak, ini tidak ada hubungannya dengan berlawanan dengan intuisi. Hanya saja ruang lingkup leksikal nama-nama variabel adalah fungsi; loop tidak memperkenalkan ruang lingkup leksikal. Fungsinya juga bekerja dengan cara yang sama di Javascript. Jika Anda membutuhkan ruang lingkup untuk var, Anda selalu dapat melakukannya (lambda scopedvar: lambda x: scopedvar + x) ()
Antti Haapala
6

Saya baru saja memulai Python dan menjalankan kepala pertama ke Lambda- yang butuh waktu beberapa saat untuk mencari tahu.

Perhatikan bahwa ini bukan suatu penghukuman terhadap apa pun. Setiap orang memiliki serangkaian hal berbeda yang tidak mudah datang.

Apakah lambda salah satu item bahasa yang 'menarik' yang dalam kehidupan nyata harus dilupakan?

Tidak.

Saya yakin ada beberapa kasus tepi di mana mungkin diperlukan, tetapi mengingat ketidakjelasan itu,

Itu tidak jelas. 2 tim terakhir yang saya kerjakan, semua orang menggunakan fitur ini sepanjang waktu.

potensi itu didefinisikan ulang dalam rilis mendatang (asumsi saya berdasarkan berbagai definisi itu)

Saya telah melihat tidak ada proposal serius untuk mendefinisikannya kembali dengan Python, di luar memperbaiki semantik penutupan beberapa tahun yang lalu.

dan kejelasan coding yang berkurang - haruskah itu dihindari?

Tidak kalah jelas, jika Anda menggunakannya dengan benar. Sebaliknya, memiliki lebih banyak konstruksi bahasa yang tersedia meningkatkan kejelasan.

Ini mengingatkan saya pada overflow (buffer overflow) dari tipe C - menunjuk ke variabel teratas dan overloading untuk mengatur nilai-nilai bidang lainnya ... semacam kecakapan memainkan pertunjukan techie tapi mimpi buruk coder maintenance ..

Lambda seperti buffer overflow? Wow. Saya tidak bisa membayangkan bagaimana Anda menggunakan lambda jika Anda pikir itu adalah "mimpi buruk pemeliharaan".

Ken
sumber
5
-1 untuk membuat saya (dan lainnya) membaca seluruh pertanyaan lagi. Perhatikan bahwa orang lain berhasil menjawab tanpa melakukannya.
Paweł Polewicz
6

Saya menggunakan lambdas untuk menghindari duplikasi kode. Ini akan membuat fungsinya dengan mudah dipahami. Misalnya:

def a_func()
  ...
  if some_conditon:
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)
  else
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)

Saya menggantinya dengan temp lambda

def a_func()
  ...
  call_big_f = lambda args_that_change: call_some_big_func(arg1, arg2, arg3, args_that_change)
  if some_conditon:
     ...
     call_big_f(argX)
  else
     ...
     call_big_f(argY)
balki
sumber
5

Saya mulai membaca buku David Mertz hari ini 'Text Processing in Python.' Sementara ia memiliki deskripsi yang cukup singkat tentang Lambda, contoh-contoh dalam bab pertama dikombinasikan dengan penjelasan dalam Lampiran A membuat mereka melompat dari halaman untuk saya (akhirnya) dan tiba-tiba saya mengerti nilai mereka. Itu tidak berarti penjelasannya akan bekerja untuk Anda dan saya masih pada tahap penemuan jadi saya tidak akan mencoba untuk menambahkan tanggapan ini selain dari yang berikut: Saya baru di Python Saya baru di OOP Lambdas adalah perjuangan untuk saya Sekarang saya membaca Mertz, saya pikir saya mendapatkannya dan saya melihat mereka sangat berguna karena saya pikir mereka memungkinkan pendekatan yang lebih bersih untuk pemrograman.

Dia mereproduksi Zen Python, satu baris yang Sederhana lebih baik daripada kompleks. Sebagai programmer non-OOP membaca kode dengan lambdas (dan sampai minggu lalu daftar pemahaman) saya pikir- ini sederhana? . Saya akhirnya menyadari hari ini bahwa sebenarnya fitur-fitur ini membuat kode jauh lebih mudah dibaca, dan dapat dimengerti daripada alternatif-yang selalu merupakan semacam loop. Saya juga menyadari bahwa seperti laporan keuangan-Python tidak dirancang untuk pengguna pemula, melainkan dirancang untuk pengguna yang ingin mendapatkan pendidikan. Saya tidak percaya betapa kuatnya bahasa ini. Ketika saya sadar (akhirnya) tujuan dan nilai lambda saya ingin meringkas sekitar 30 program dan mulai memasukkan lambda di mana sesuai.

PyNEwbie
sumber
5

Kasus yang berguna untuk menggunakan lambdas adalah untuk meningkatkan keterbacaan pemahaman daftar panjang . Dalam contoh loop_dicini singkat untuk kejelasan tetapi bayangkan loop_dicsangat panjang. Jika Anda hanya akan menggunakan nilai polos yang mencakup ialih-alih versi lambda dari nilai itu, Anda akan mendapatkan NameError.

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> loop_dic = lambda i: {"name": i["name"] + " Wallace" }
>>> new_lis = [loop_dic(i) for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

Dari pada

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> new_lis = [{"name": i["name"] + " Wallace"} for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]
Bentley4
sumber
5

Saya dapat memberikan contoh di mana saya benar-benar membutuhkan lambda. Saya membuat program grafis, di mana penggunaan klik kanan pada file dan menetapkan salah satu dari tiga opsi. Ternyata di Tkinter (program antarmuka GUI saya menulis ini), ketika seseorang menekan tombol, itu tidak dapat ditugaskan ke perintah yang mengambil argumen. Jadi jika saya memilih salah satu opsi dan ingin hasil dari pilihan saya adalah:

print 'hi there'

Maka bukan masalah besar. Tetapi bagaimana jika saya membutuhkan pilihan saya untuk memiliki detail tertentu. Sebagai contoh, jika saya memilih pilihan A, itu memanggil fungsi yang mengambil dalam beberapa argumen yang bergantung pada pilihan A, B atau C, TKinter tidak dapat mendukung ini. Lamda adalah satu-satunya pilihan untuk menyiasati ini ...

Glueberg
sumber
2
Yah, mungkin Anda bisa melakukannya def foo... dan kemudian diteruskan di foobukannya lambda. Itu lebih banyak kode dan Anda harus datang dengan nama.
Jon Coombs
4

Saya sering menggunakannya, terutama sebagai objek nol atau untuk sebagian mengikat parameter ke suatu fungsi.

Berikut ini contohnya:

untuk menerapkan pola objek nol:

{
    DATA_PACKET: self.handle_data_packets
    NET_PACKET: self.handle_hardware_packets
}.get(packet_type, lambda x : None)(payload)

untuk pengikatan parameter:

katakanlah saya memiliki API berikut

def dump_hex(file, var)
    # some code
    pass

class X(object):
    #...
    def packet_received(data):
        # some kind of preprocessing
        self.callback(data)
    #...

Lalu, ketika saya tidak ingin dengan cepat membuang data yang diterima ke file saya melakukan itu:

dump_file = file('hex_dump.txt','w')
X.callback = lambda (x): dump_hex(dump_file, x)
...
dump_file.close()
Piotr Czapla
sumber
4

saya menggunakan lambda untuk membuat panggilan balik yang menyertakan parameter. Lebih bersih menulis lambda dalam satu baris daripada menulis metode untuk melakukan fungsi yang sama.

Sebagai contoh:

import imported.module

def func():
    return lambda: imported.module.method("foo", "bar")

sebagai lawan:

import imported.module

def func():
    def cb():
        return imported.module.method("foo", "bar")
    return cb
NuclearPeon
sumber
4

Saya pemula python, jadi untuk mendapatkan ide yang jelas tentang lambda saya membandingkannya dengan loop 'untuk'; dalam hal efisiensi. Berikut kodenya (python 2.7) -

import time
start = time.time() # Measure the time taken for execution

def first():
    squares = map(lambda x: x**2, range(10))
    # ^ Lambda
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0 seconds

def second():
    lst = []
    for i in range(10):
        lst.append(i**2)
    # ^ a 'for' loop
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0019998550415 seconds.

print abs(second() - first()) # Gives 0.0019998550415 seconds!(duh)
Pratik Kulkarni
sumber
6
Anda mungkin tertarik pada timeitmodul, yang biasanya memberikan hasil yang lebih akurat daripada mengurangi time.time()nilai.
Kevin
2
Hmm, bukankah Anda perlu me-restart timer Anda di awal pertama () dan kedua ()?
qneill
2

Lambda adalah pembangun prosedur. Anda dapat mensintesis program saat dijalankan, meskipun lambda Python tidak terlalu kuat. Perhatikan bahwa hanya sedikit orang yang mengerti pemrograman semacam itu.

Nick Dandoulakis
sumber