Python lambdas neden yararlıdır? [kapalı]


929

Python lambdaları bulmaya çalışıyorum. Lambda gerçek hayatta unutulması gereken "ilginç" dil öğelerinden biri mi?

Eminim ihtiyaç duyulabilecek bazı uç durumlar vardır, ancak belirsizliği göz önüne alındığında, gelecekteki sürümlerde potansiyelinin yeniden tanımlanması (çeşitli tanımlara dayanan varsayımım) ve azaltılmış kodlama netliği - gerekiyorsa kaçınılmalıdır?

Bu bana C tiplerinin taşmasını (arabellek taşması) hatırlatıyor - üst değişkeni işaret ediyor ve diğer alan değerlerini ayarlamak için aşırı yükleniyor. Bir çeşit teknisyen şovu gibi geliyor ama bakım kodlayıcı kabusu.


261
+1 İyi soru - kötü varsayımlar (lambda'nın belirsizliği) =) Programlama tekniklerini yargılamamaya çalışın. Bunları değerlendirin ve zihinsel araç setinize ekleyin. Onlardan hoşlanmıyorsanız, onları kullanmayın ve dindar olmadan mantıklı bir şekilde tartışmaya hazır olun.
Kieveli

41
Haskell Kuralları! Lambda fonksiyonları size ifade ve soyutlama gücü verir.
Jonathan Barbero

11
@JAL LISP'den bahsetmiyorum ...
YaklaşıyorDarknessFish

8
@ApproachingDarknessFish "Ah, bu babanın Parenthesis. Daha medeni bir çağdan daha uygar bir silah." - Obi Lisp Kenobi
Alanlar

Yanıtlar:


1009

Lambda fonksiyonları hakkında mı konuşuyorsunuz ? Sevmek

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

Bu şeyler aslında oldukça faydalı. Python denilen programlama stili destekler fonksiyonel programlama sen şeyler yapmak için diğer işlevlere işlevler geçebilir. Misal:

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

kümeler mult3için [3, 6, 9], bu (bir iddia olabilir, daha net ve) kısadır 3. katları olan orijinal liste olan elemanlardır daha

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

Tabii ki, bu özel durumda, bir liste kavrayışı ile aynı şeyi yapabilirsiniz:

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

(ya da hatta range(3,10,3)), ancak bir liste kavrama kullanamayacağınız ve lambda işlevinin bir şey yazmanın en kısa yolu olabileceği daha karmaşık, daha karmaşık kullanım durumları vardır.

  • Bir işlevi başka bir işlevden döndürme

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

    Bu genellikle Python'un dekoratörleri gibi işlev sarmalayıcıları oluşturmak için kullanılır.

  • Yinelenebilir bir dizinin elemanlarını 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'
  • Alternatif bir tuşa göre sıralama

    >>> 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]

Lambda fonksiyonlarını düzenli olarak kullanıyorum. Onlara alışmak biraz zaman aldı, ama sonunda dilin çok değerli bir parçası olduklarını anladım.


26
Örnekleri seviyorum, anlaması çok kolay. Ama azaltmak için. Bu özelliği uygulamak zorunda kalırsam. Yapacağım','.join(str(x) for x in [1,2,3,4,5,6,7,8,9])
etlds

3
BTW bunu Python3 üzerinde çalıştırırsanız, gerçek değerleri görmek için filtre sonuçlarında liste çağırmanız gerekir, ayrıca functools'tan içe aktarmanız gerekir
Gerard

Yukarıdaki "fonksiyonel programlama" tanımından emin miyiz? Bana biraz kafa karıştırıcı geldi.
stdout

3
Bence kilit nokta, lambdafonksiyonların anonim olabileceğidir (tüm örneklerinizde olduğu gibi). Herhangi bir lambdaşeye bir işlev atarsanız, o zaman yanlış yapıyorsunuz ve defbunun yerine kullanmalısınız
Chris_Rands

1
@zgulser Bu bir tanım değil, sadece işlevsel programlamanın yapmanıza izin verdiği bir şey hakkında bir açıklama.
David Z

377

lambdasadece süslü bir söylem biçimidir function. Adı dışında, bu konuda belirsiz, korkutucu veya şifreli bir şey yoktur. Aşağıdaki satırı okuduğumda yerine lambdagöre functionkafanızda:

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

Sadece bir işlevini tanımlar x. Bazı diğer diller, Raçık bir şekilde söylüyorlar:

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

Anlıyorsun? Programlamada yapılacak en doğal şeylerden biri.


36
Bu, programlama dışı geçmişlerden gelenler için harika bir açıklamadır (yani: tam bilimler), anlamını lambda çok basit hale getirir . Teşekkürler!
Gabriel

10
Raymond Hettinger, görüşmelerinden birinde adı yaktı ve 'lambda' yerine 'işlev yap' adını vererek tüm karışıklığın önlenebileceğini söyledi. :-)
ankush981

10
yerine lambdagöre functionkafanızda ve eklemek returngeçen ifadenin önce
Ciprian Tomoiagă

4
@AaronMcMillin Deneyin type(lambda x: 3). lambdaifadeler ve defifadeler hem functionnesne üretir ; yalnızca hangi örnekleri üretebileceğini lambdasınırlayan bir ifadenin sözdizimidir .
chepner

6
@AaronMcMillin Demek istediğim eksik. Tanımlamak olamaz diye her bir ile işlevini lambdaifade bir sonucudur anlamına gelmez lambdaifadesi değildir bir fonksiyonu.
chepner

107

İki satırlı özet:

  1. Kapaklar : Çok faydalı. Öğrenin, kullanın, sevin.
  2. Python'un lambdaanahtar kelimesi: gereksiz, bazen yararlı. Kendinizle uzaktan karmaşık bir şey yaptığını görürseniz, onu bırakın ve gerçek bir işlev tanımlayın.

72

Bir lambda, yüksek dereceli işlevlerle ilgilenen çok önemli bir soyutlama mekanizmasının bir parçasıdır. Değerinin doğru anlaşılması için lütfen Abelson ve Sussman'dan yüksek kaliteli dersler izleyin ve SICP kitabını okuyun

Bunlar, modern yazılım işindeki ilgili konular ve giderek daha popüler hale geliyor.


1
Lambda ifadeleri diğer dillerde de (C # gibi) popüler hale geliyor. Hiçbir yere gitmiyorlar. Kapakları okumak Lambdaları anlamak için yararlı bir egzersiz olacaktır. Kapaklar, jQuery gibi çerçevelerde çok fazla kodlama büyüsünü mümkün kılar.
Dan Esparza

3
lambdaS ve birinci sınıf fonksiyonları karıştırmayın . Python son derece sınırlı bir lambdaifadeye sahiptir, ancak tamamen birinci sınıf işlevlere sahiptir. Yaptığı tek fark, geçmek istediğiniz işlevleri adlandırmanız gerektiğidir.
Gareth Latty

59

lambdalar GUI programlamasında son derece kullanışlıdır. Örneğin, bir grup düğme oluşturduğunuzu ve düğme başına benzersiz bir geri arama yerine tek bir paramaterize geri arama kullanmak istediğinizi varsayalım. Lambda bunu kolaylıkla gerçekleştirmenizi sağlar:

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

(Not: Her ne kadar bu soru özellikle soruyor olsa da) lambda sorulsa da , aynı tür sonuçları elde etmek için functools.partial da kullanabilirsiniz )

Alternatif olarak, her düğme için yinelenen koda yol açabilecek ayrı bir geri arama oluşturmaktır.


1
Tam olarak bu yüzden lambda'nın ne olduğunu araştırdım, ama bu neden işe yarıyor, bana göre sadece işlevi çağırmakla aynı görünüyor ( stackoverflow.com/questions/3704568/… ). Belki geç, işe yarıyor, ama neden işe yarıyor?
Rqomey

5
@Rqomey: Fark, bu örnekte valuebir döngü içinde tanımlanmış olmasıdır; diğer örnekte parametrenin her zaman sadece bir değeri vardır. Gibi bir şey eklediğinizde arg=value, geçerli değeri geri aramaya eklersiniz . Bu olmadan, geri aramadaki değişkene bir referans bağlarsınız. Referans, her zaman değişkenin son değerini içerecektir, çünkü geri arama, döngü zaten çalışmayı bitirdikten bir süre sonra gerçekleşir.
Bryan Oakley

1
Dün bu çalışmayı aldım, dürüstçe ne kadar yararlı olduğuna inanamıyorum ... Döngü için bir menü ve yapılandırma için bir csv dosyası oluşturabilirim. Gerçekten faydalı şeyler.
Rqomey

1
Varlığını not edin functools.partial(), bunu daha az sarsıntı ile (ve olmadan lambda) yapmanızı sağlar .
Gareth Latty

2
partial(my_callback, value)vs lambda arg=value: my_callback(arg)- lambda çok daha fazla sarsıntıya sahiptir (arg ve sonra kullanıma atama) ve niyetin ne olduğu daha az açıktır (lambda'da farklı bir şey yapıyor olabilirsiniz). İthalat gerçekten bir sorun değil (yine de bir yığın var ve dosya başına bir kez). Kod en iyi ne kadar iyi okuduğuna karar verir ve partial()okumak lambdadan çok daha kolaydır.
Gareth Latty

58

Lambda'nın gideceğinden şüpheliyim. Sonunda kaldırmak için vazgeçmek hakkında Guido'nun gönderisine bakın . Ayrıca çatışmanın ana hatlarına da bakınız .

Python'un işlevsel özelliklerinin arkasındaki anlaşma hakkında daha fazla bilgi için bu gönderiye göz atabilirsiniz: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

İlginçtir ki, lambda ve diğer fonksiyonel özelliklerin kullanılmasını başlangıçta motive eden harita, filtre ve azaltma işlevlerinin yerini büyük ölçüde liste kavrayışları ve jeneratör ifadeleri almıştır. Aslında, azaltma işlevi Python 3.0'daki yerleşik işlevler listesinden kaldırıldı. (Ancak, lambda, harita veya filtrenin kaldırılmasıyla ilgili şikayetleri göndermek gerekli değildir: kalıyorlar. :-)

Kendi iki sentim: Nadiren, berraklık giderken buna değecek lambda. Genellikle lambda içermeyen daha açık bir çözüm vardır.


2
azaltmanın Python 3.0'da hala geçerli olduğunu unutmayın. GERÇEKTEN isterseniz, yine de sahip olabilirsiniz.
Paweł Polewicz

Guido'nun girişimi daha çok sözdizimi hakkındaydı. Bu kişi ayrıca şunu düşünüyor: cackhanded.com/blog/post/2008/01/24/…
leewz

38

Python'da, lambdaişlevleri satır içinde tanımlamanın bir yoludur,

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

ve..

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

.. tam olarak aynı.

Normal bir işlevle yapamayacağınız lambda ile yapabileceğiniz hiçbir şey yoktur - Python işlevlerinde her şey gibi bir nesnedir ve lambdalar basitçe bir işlevi tanımlar:

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

Dürüstçe düşünüyorum ki lambda anahtar kelimenin Python'da gereksiz bunları kullanmaya hiç ihtiyacım olmadı (veya normal bir işlev, liste kavrama veya birçok yerleşik işlevden birinin daha iyi kullanılabileceği yerlerde kullanıldığını görmedim)

Tamamen rastgele bir örnek için, "Python'un lambdası bozuldu!" :

Lambda'nın nasıl kırıldığını görmek için, fs=[f0,...,f9]nerede bir işlev listesi oluşturmayı deneyin fi(n)=i+n. İlk girişim:

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

Bu işe yarasa bile, korkunç ve "unpythonic" olsa da, aynı işlevselliğin sayısız başka yolla yazılabileceğini savunuyorum, örneğin:

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

Evet değil aynı, ama var asla bir listede lambda fonksiyonları bir grup oluşturarak gerekli olan bir nedenini görüldü. Diğer dillerde mantıklı gelebilir, ancak Python Haskell (veya Lisp veya ...) değildir.

Lütfen lambda'yı kullanabileceğimizi ve yine de istenen sonuçları bu şekilde elde edebileceğimizi unutmayın:

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

Düzenle:

Lambda'nın yararlı olduğu birkaç durum vardır, örneğin PyQt uygulamalarına sinyalleri bağlarken, genellikle aşağıdaki gibi uygundur:

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

Sadece yapmak w.textChanged.connect(dothing)dothing yöntemi ekstra bir eventargüman ile çağırır ve bir hataya neden olur. Lambda kullanmak, bir sarma işlevini tanımlamak zorunda kalmadan argümanı düzenli bir şekilde bırakabileceğimiz anlamına gelir.


2
"lambda bozuldu" argümanınız bozuldu, çünkü python değişken kapsam belirleme kuralları bu şekilde çalışıyor, nokta. Döngü içinde bir kapak oluşturduysanız aynı şekilde ısırılırsınız.
Antti Haapala

1
lambda, diğer birçok dilde olduğu gibi (örneğin, javascript) kullanıcıya "anonim" bir işlev sunmanın sadece bir yoludur.
Stefan Gruenwald

1
aTanımladığınız lambda ve işlevler tam olarak aynı değildir . :) __name__En azından tarlaya göre farklılık gösterir ...
nperson325681

1
Satır içi bir işlevden daha fazlası çalışır.
kta

"Başka bir dilde mantıklı gelebilir" konusundaki argümanınız tuhaf. Ya lambdaların kendine has nitelikleri var ya da değiller.
Titou

31

Lambda'yı, aynı şeyi yapan, ancak farklı durumlar için bir işlev listesi için yararlı buluyorum.

Gibi Mozilla çoğul kuralları :

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'

Tüm bunlar için bir işlev tanımlamanız gerekirse, sonuna kadar delirirsiniz.
Ayrıca, işlev isimleriyle hoş olmazdı plural_rule_1,plural_rule_2 vb Ve gerekiyordu eval()Eğer bir değişken fonksiyon id bağlı yaparken bunun.


1
Bu, şimdiye kadar desen eşleştirme ve seçeneklerle F #'da yaşadığım kısa karşılaşmalara benziyor. Bu sözdiziminin nasıl kullanılacağı hakkında daha fazla bilginiz var mı?
Ken

26

Sizinle yapabileceğiniz hemen hemen her şey, lambdaadlandırılmış işlevler veya liste ve jeneratör ifadeleri ile daha iyi yapabilir.

Sonuç olarak, çoğunlukla temelde herhangi bir durumda olanlardan sadece biri olmalısınız (belki de interaktif yorumlayıcıda yazılan kod kodu hariç).


3
"Çoğunlukla her durumda olanlardan sadece biri olmalısın" Dönemi. Lambda'yı tercümana yazmak o kadar da yararlı değil.
S.Lott

11
@Javier "lambda" konseptinden bahsediyorsan sana katılıyorum; ancak, "lambda" hakkında python anahtar sözcüğünden bahsediyorsak: 1) adlandırılmış işlevler daha hızlıdır ve lambdas (harita + filtre) kullandığınız hemen hemen her yerde daha fazla şey yapabilir (ifadeler + ifadeler) daha performans ve özlü. Ben birinci sınıf fonksiyonlar serin değil, sadece python "lambda" anahtar kelime sadece adlandırılmış bir işlevi kullanmak kadar iyi değil demiyorum, hepsi bu.
Aaron Maenpaa

3
lambda, sort =) ve sort () için key = argüman gibi geri çağrı argümanları alan işlevlerle kullanım için benim için vazgeçilmez oldu
Rick Copeland

19
@ Bundan şüphem yok, ama gerçek şu ki, "lambda" yı gördüğünüzde ve "zohmygod lambda" yı düşündüğünüzde ve python'da şema kodu yazmaya başladığınızda, python'un lambda ifadesinin sınırlamaları sizi hayal kırıklığına uğratırsa. Öte yandan, kendi kendinize düşünmeye başlarsanız "Bir liste anlama işe yarayacak mı? Hayır. İhtiyacım olan şey, adlandırılmış bir işlev olmaktan fayda sağlayacaktır mi? Hayır. x.height) ", muhtemelen lambda'yı doğru sayıda kullanacaksınız.
Aaron Maenpaa

4
+1: Bir lambda kullandığında isimsiz bir işlev kullandığını yeterince vurgulayamıyorum . Ve isimlerin değerli bir entelektüel katma değeri var.
Stephane Rolland

19

Python'u birkaç yıldır kullanıyorum ve lambda'ya ihtiyaç duyduğum bir davaya hiç girmedim. Gerçekten, öğretici belirttiği gibi, sadece sözdizimsel şeker içindir.


8
Bunlar çok python kullanırken bir GUI geliştirirken yararlıdır. Genellikle, widget'ların bir işleve başvurması gerekir. Bir işlevi çağırmak ve bağımsız değişkenleri iletmek için bir widget'a ihtiyacınız varsa, lambda bunu yapmanın çok uygun bir yoludur.
Bryan Oakley

1
Birden fazla argümanı işleve geçirmenin avantajı nedir? func_name (a, b): lambda kullanmak yerine a + b
döndür

2
gerekli değildir, ancak daha kısa kod yazmaya ve birçok durumda daha okunabilir olmasına yardımcı olur, esp. Java veya C ++ gibi ayrıntılı dillerde
phuclv

17

Python'un lambda'nın özel uygulamasıyla konuşamam, ancak genel olarak lambda fonksiyonları gerçekten kullanışlı. İşlevsel programlamanın temel bir tekniği (hatta THE tekniği) ve nesne yönelimli programlarda da çok kullanışlıdır. Bazı problem türleri için en iyi çözümdür, bu yüzden kesinlikle unutulmamalıdır!

Neden yararlı olduğunu görmek için kapanışları ve harita işlevini (python belgelerine bağlanan, ancak işlevsel yapıları destekleyen hemen hemen her dilde var) okumanızı öneririm .


3
Bu şeyler lambdas olmadan yapılabilir. Sadece büyük bir güçlük.
Brian

17

Lambda işlevi, bir işlev oluşturmanın bürokratik olmayan bir yoludur.

Bu kadar. Örneğin, ana fonksiyonunuza sahip olduğunuzu ve değerlerin kare olması gerektiğini varsayalım. Bunu yapmanın geleneksel yolunu ve lambda yolunu görelim:

Geleneksel yol:

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

def square(x):
    return x**2

Lambda yolu:

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

Farkı gör?

Lambda işlevleri listelerin anlaşılması veya harita gibi listelerde çok iyi gider. Aslında, liste kavrama lambda kullanarak kendinizi ifade etmek için "pitonik" bir yoludur. Ör:

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

Sözdiziminin her bir öğesinin ne anlama geldiğini görelim:

[]: "Bana bir liste ver"

x ** 2: "bu yeni doğan işlevi kullanma"

a'daki x için: "a'daki her öğeye"

Bu uygun mu? Bunun gibi fonksiyonlar yaratmak. Lambda kullanarak yeniden yazalım:

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

Şimdi aynı şey olan ama dili dilden bağımsız bir harita kullanalım. Haritalar 2 argüman alır:

(i) bir işlev

(ii) tekrarlanabilir

Ayrıca, her öğenin, yinelenebilir öğenin her öğesine uygulandığı işlevin bir listesini verir.

Yani, haritayı kullanarak:

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

Lambdalarda ve haritalamada ustalaşırsanız, verileri manipüle etmek ve özlü bir şekilde büyük bir güce sahip olacaksınız. Lambda işlevleri ne anlaşılır ne de kod netliğini ortadan kaldırıyor. Zor bir şeyi yeni bir şeyle karıştırmayın. Onları kullanmaya başladığınızda, çok net bulacaksınız.


13

lambdaBence bu konuda güzel olan şeylerden biri , değer gerekene kadar basit formlar için bir değerlendirmeyi ertelemenin yolu. Açıklamama izin ver.

Birçok kütüphane rutini, belirli parametrelerin (lambda'nın biri olduğu) callables olmasına izin verecek şekilde uygulanır. Fikir, gerçek değerin sadece kullanılacağı zamanda (çağrıldığında değil) hesaplanacağıdır. (Tutarlı) bir örnek, konuyu açıklamaya yardımcı olabilir. Belirli bir zaman damgasını günlüğe kaydedecek bir rutininiz olduğunu varsayalım. Rutinin geçerli saati eksi 30 dakika kullanmasını istiyorsunuz. Buna şöyle derdiniz

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

Şimdi gerçek fonksiyonun sadece belirli bir olay meydana geldiğinde çağrıldığını ve zaman damgasının sadece o anda hesaplanmasını istediğinizi varsayalım. Bunu böyle yapabilirsin

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

log_timestampKutunun böyle callables ile başa çıkabileceğini varsayarsak, ihtiyaç duyduğunda bunu değerlendirir ve o zaman zaman damgasını alırsınız.

Elbette bunu yapmanın alternatif yolları var ( operatorörneğin modülü kullanarak ) ama umarım konuyu aktardım.

Güncelleme : İşte biraz daha somut gerçek dünya örneği.

Güncelleme 2 : Bence bu thunk denilen şeyin bir örneği .


11

Yukarıda belirtildiği gibi, Python'daki lambda operatörü anonim bir işlevi tanımlar ve Python işlevlerinde kapaklardır. Kapatma konseptini, onlar için sadece sözdizimsel metadon olan operatör lambda ile karıştırmamak önemlidir.

Python'da birkaç yıl önce başladığımda, lambdas'ı çok iyi kullandım, liste kavrayışlarıyla birlikte havalı olduklarını düşündüm. Bununla birlikte, Python'da yazılan büyük bir web sitesini birkaç bin işlev puanı sırasına göre yazdım ve sürdürmem gerekiyor. Deneyimlerden lambdas'ın şeyleri prototiplemek için uygun olabileceğini öğrendim, ancak birkaç anahtar stok kaydetmek veya bazen değil, satır içi işlevler (adlandırılmış kapaklar) üzerinde hiçbir şey sunmuyorum.

Temel olarak bu birkaç noktaya kadar kaynar:

  • anlamlı isimler kullanılarak açıkça yazılan yazılımları okumak daha kolaydır. Tanıma göre anonim kapanmalar, isimleri olmadığı için anlamlı bir ada sahip olamazlar. Bu kısalık, bir nedenden dolayı, lambda parametrelerini de enfekte ediyor gibi görünüyor, bu nedenle lambda x: x + 1 gibi örnekleri sık sık görüyoruz
  • adlandırılacak kapakların yeniden adlandırılması daha kolaydır, çünkü bunlara atıfta bulunulacak bir ad olduğunda birden çok kez adlarıyla anılabilirler.
  • lambda yerine adlandırılmış kapanışları kullanan kodda hata ayıklamak daha kolaydır, çünkü ad geri izlemelerde ve hatanın etrafında görünür.

Onları toplayıp adlandırılmış kapaklara dönüştürmek için yeterli sebep. Ancak, anonim kapanmalara karşı iki kin daha tutuyorum.

İlk kin, sadece dili karıştırmaya yarayan başka bir gereksiz anahtar kelime olmasıdır.

İkinci kin daha derin ve paradigma seviyesinde, yani fonksiyonel bir programlama stilini teşvik etmelerini sevmiyorum, çünkü bu stil mesaj geçirme, nesne yönelimli veya prosedürel stillerden daha az esnektir, çünkü lambda hesabı Turing- tamamlandı (Neyse ki Python'da, bir lambda içinde bile bu kısıtlamayı kaldırabiliriz). Lambdaların bu tarzı teşvik etmelerinin nedenleri:

  • Örtük bir geri dönüş vardır, yani işlevler 'olması gerektiği' gibi görünürler.

  • Bunlar, başka, daha açık, daha okunabilir, daha yeniden kullanılabilir ve daha genel bir mekanizmaya alternatif bir devlet gizleme mekanizmasıdır: yöntemler.

Lambda içermeyen Python yazmak ve lambdaları görünürde kaldırmak için çok çalışıyorum. Python'un lambdalar olmadan biraz daha iyi bir dil olacağını düşünüyorum, ama bu sadece benim düşüncem.


1
msgstr "" ... Python fonksiyonlarında kapanışlardır ". Anladığım kadarıyla bu doğru değil. Kapaklar işlevlerdir, ancak işlevler her zaman kapanmaz. İşlev-> lambda x, y: x + y. Kapatma-> lambda x: lambda y: x + y
0atman

6
"Lambda hesabı Turing-complete olmadığından" basit yanlış, türlenmemiş lambda hesabı IS Turing tamamlandı, bu yüzden bu kadar önemli. Y-birleştiriciyi kullanarak özyineleme alabilirsiniz,Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
Antti Haapala

Dahası, Turing bütünlüğünü okumak için Wikipedia'ya giderse, "Klasik bir örnek lambda hesabıdır" der.
Antti Haapala

cidden - Tamamlanmıyor - bu yanıtın ciddi bir düzenleme veya geri çekilmesi gerekiyor.
Tony Suffolk 66

@ MarcinŁoś KISS'e bağlı olduğu için oy kullandı. Bir karşılaştırma olarak, K&R kitabı ödevi bir parça veya daha büyük bir ifade olarak kullanırken daha kompakt olduğunu, ancak daha az okunabilir olduğunu belirtmektedir. Fonksiyonel programlama kalıplarını kullanma eğilimi trit ve klişedir. Nasıl kullanılabileceklerini belirtmek yeterlidir, ancak yetkili bir geliştirici olmak için çok önemli olduklarını belirtmek çok heveslidir; tamamen öznel. Bu argüman, sınıfsız dillerin ilkel, aşağı ve yetersiz olduğunu iddia eden C ++ geliştiricilerine benzer. "Turing-completeeness", argümanlar bilgiçlikçidir.
typedeaf

11

Lambdas aslında fonksiyonel programlamadaki fikirlerden kaynaklanan çok güçlü yapılardır ve Python'un yakın gelecekte hiçbir şekilde kolayca gözden geçirilemeyecek, yeniden tanımlanmayacak veya kaldırılamayacak bir şeydir. Fonksiyonları parametre olarak geçirmenize izin verdiği için daha güçlü olan kod yazmanıza yardımcı olurlar, böylece birinci sınıf vatandaşlar olarak fonksiyon fikri.

Lambdas kafa karıştırıcı olma eğilimindedir, ancak sağlam bir anlayış elde edildikten sonra, böyle temiz zarif bir kod yazabilirsiniz:

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

Yukarıdaki kod satırı, listedeki sayıların karelerinin bir listesini döndürür. Tabii ki, bunu da yapabilirsiniz:

def square(x):
    return x*x

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

Önceki kodun daha kısa olduğu açıktır ve özellikle harita işlevini (veya parametre olarak bir işlevi alan benzer bir işlevi) tek bir yerde kullanmayı düşünüyorsanız bu doğrudur. Bu aynı zamanda kodu daha sezgisel ve zarif hale getirir.

Ayrıca, @David Zaslavsky'nin cevabında da belirtildiği gibi, özellikle listeniz belirsiz bir matematiksel yoldan değerler almak zorundaysa, liste kavrayışları her zaman gitmenin yolu değildir.

Daha pratik bir bakış açısıyla, son zamanlarda benim için lambdaların en büyük avantajlarından biri GUI ve olay güdümlü programlama olmuştur. Tkinter'deki geri çağrılara bakarsanız, argüman olarak aldıkları tek şey onları tetikleyen olaydır. Örneğin

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

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

Şimdi ya geçmeniz gereken bazı argümanlarınız varsa? Bir fare tıklamasının koordinatlarını saklamak için 2 argümanı geçirmek kadar basit bir şey. Kolayca şöyle yapabilirsiniz:

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

Şimdi, bunun küresel değişkenler kullanılarak yapılabileceğini iddia edebilirsiniz, ancak özellikle küresel değişken sadece belirli bir yerde kullanılacaksa, başınızı bellek yönetimi ve sızıntı konusunda endişelenmek istiyor musunuz? Bu sadece zayıf programlama tarzı olurdu.

Kısacası, lambdalar harika ve asla hafife alınmamalıdır. Python lambdas, LISP lambdas ile aynı değildir (daha güçlüdür), ancak onlarla gerçekten çok fazla sihirli şey yapabilirsiniz.


Teşekkürler. Son örneğini tam olarak anlamadım. Hem x hem de y hem mainve hem de nasıl tanımlanır do_something_cool? İşlevde xve yişlevde ne olur ? Geçirilen değerlerin hemen üzerine yazılıyor mu? Fonksiyon nasıl biliyor event? Yorum / açıklama ekleyebilir misiniz? Teşekkürler
Sanjay Manohar

@SanjayManohar Ben geçiyorum xve yargümanlar olarak do-something-coolve değerleri beklenen hiçbir argüman geçmek için lambdas nasıl kullanabileceğinizi göstermek için ayarlanıyor. widget.bindFonksiyon bekler evento alette GUI olayını tanımlayan parametreyi. Daha fazla netlik için Tkinter'in programlama modelini okumanızı tavsiye ederim.
varagrawal

hmm sanırım Tkinter modelini anlıyorum. Ama yine de tam olarak anlamıyorum - geçip x,ygeçiyorsunuz x=event.x. Bu, geçtiğiniz değerin üzerine yazmıyor mu? Ve fonksiyon ne eventolduğunu nasıl biliyor ? Bunu işleve nereye aktardığınızı görmüyorum. Yoksa bir yöntem mi? Ayrıca işlev adında eksi işaretlerine izin veriliyor mu?
Sanjay Manohar

@SanjayManohar dostum, Tkinter ve Python'da okumalısın. Tkinter, olay nesnesine işlevi varsayılan eylem olarak iletir. Gelince x, y, bu sadece açıklama amaçlı bir örnektir. Tkinter'e değil lambdaların gücünü göstermeye çalışıyorum. :)
varagrawal

1
Tamam şimdi ne istediğini görüyorum - işlevin almasını istiyor eventmusun? bu durumda lambda okumamalı lambda event: do_something_cool(event,x,y)mı?
Sanjay Manohar

8

Lambdalar genel olarak işlevsel programlama stiliyle derinden bağlantılıdır. Bazı verilere bir işlev uygulayarak ve sonuçları birleştirerek sorunları çözebileceğiniz fikri, Google'ın algoritmalarının çoğunu uygulamak için kullandığı fikirdir.

Fonksiyonel programlama tarzında yazılan programlar kolayca paralel hale getirilir ve bu nedenle modern çok çekirdekli makinelerle giderek daha önemli hale gelir. Kısacası, HAYIR onları unutmamalısınız.


7

Lambda'yı bulmayı başaran ilk tebrikler. Benim düşünceme göre bu gerçekten güçlü bir yapı. Bu günlerde fonksiyonel programlama dillerine yönelik eğilim, kesinlikle bundan kaçınılmaması ve yakın gelecekte yeniden tanımlanmasının bir göstergesidir.

Sadece biraz farklı düşünmelisin. Eminim yakında seveceksin. Ancak sadece python ile uğraşıyorsanız dikkatli olun. Lambda gerçek bir kapanış olmadığından, bir şekilde "kırıldı": pitonlar lambda kırıldı


Python'un lambdası kırık değil. Lamdalarda yerlileri idare etmenin iki yolu vardır. Her ikisinin de avantajları ve dezavantajları vardır. Python'un (ve C #) aldığı yaklaşımın muhtemelen tamamen işlevsel dillere alışkın olanlara karşı mantıksız olduğunu düşünüyorum, çünkü tamamen işlevsel bir dille bu yaklaşımın mantıklı olduğunu düşünmüyorum.
Brian

Gerçekten mantıksız. Ben bir python programcısı değilim ama gıcırtı smalltalk aynıdır ve düzenli olarak buna rastlamak. Bu yüzden ben bile "kırık" olduğunu düşünürdüm :)
Norbert Hartl

Hayır, bunun mantıksızlık ile ilgisi yoktur. Değişken isimlerinin sözlüksel kapsamı bir fonksiyonun kapsamıdır; bir döngü sözcüksel bir kapsam tanımaz. Javascript'te de fonksiyonlar aynı şekilde çalışır. Var için bir kapsama ihtiyacınız varsa, her zaman yapabilirsiniz (lambda scopedvar: lambda x: scopedvar + x) ()
Antti Haapala

6

Sadece Python'a başlıyorum ve önce Lambda'ya doğru koştum - bu da anlaması biraz zaman aldı.

Bunun hiçbir şeyin kınanması olmadığını unutmayın. Herkesin kolay gelmeyen farklı şeyleri vardır.

Lambda, gerçek hayatta unutulması gereken 'ilginç' dil öğelerinden biri mi?

Hayır.

Eminim ihtiyaç duyulabilecek bazı uç durumlar vardır, ancak belirsizliği göz önüne alındığında,

Karanlık değil. Çalıştığım son 2 ekip, herkes bu özelliği her zaman kullandı.

gelecekteki sürümlerde potansiyelinin yeniden tanımlanması (çeşitli tanımlara dayanarak varsayım)

Birkaç yıl önce kapanış semantiğini düzeltmenin ötesinde, Python'da yeniden tanımlamak için ciddi bir teklif görmedim.

ve kodlama netliğinin azalması - bundan kaçınılmalı mı?

Doğru kullanırsanız, daha az net değildir. Aksine, daha fazla dil yapısına sahip olmak açıklığı artırır .

Bu bana C tiplerinin taşmasını (arabellek taşması) hatırlatıyor - üst değişkene işaret ediyor ve diğer alan değerlerini ayarlamak için aşırı yükleniyor ... bir çeşit teknoloji şovu ama bakım kodlayıcı kabusu ..

Lambda tampon taşması gibi mi? Vay. Eğer bir "bakım kabusu" olduğunu düşünüyorsanız lambda nasıl kullandığını hayal edemiyorum.


5
Beni (ve diğerlerini) tüm soruyu tekrar okutmak için -1. Başkalarının bunu yapmadan cevap vermeyi başardığını unutmayın.
Paweł Polewicz

6

Kod çoğaltmasını önlemek için lambdas kullanıyorum. İşlevi kolayca anlaşılabilir yapacaktır Örn:

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

Bunu temp lambda ile değiştiriyorum

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)

5

David Mertz'in bugün 'Python'da Metin İşleme' kitabını okumaya başladım. Lambda'nın oldukça kısa bir tanımı olsa da, ilk bölümdeki örnekler Ek A'daki açıklama ile birleştiğinde, onları benim için sayfadan atladı (sonunda) ve aniden değerlerini anladım. Bu, açıklamasının sizin için işe yarayacağı anlamına gelmiyor ve hala keşif aşamasındayım, bu yüzden aşağıdakilerden başka bu yanıtları eklemeye çalışmayacağım: Python için yeniyim OOP Lambdas için yeni biriyim. Şimdi Mertz'i okuduğum için, onları aldığımı düşünüyorum ve onları programlamaya daha temiz bir yaklaşıma izin verdiklerini düşündüğüm kadar kullanışlı buluyorum.

Biri basit olan Python'un Zen'ini yeniden üretir, karmaşık olmaktan iyidir. OOP olmayan bir programcı olarak lambdas ile kod okuma (ve geçen hafta liste anlama kadar) düşündüm- Bu basit mi? . Nihayet bugün bu özelliklerin kodu çok daha okunaklı ve anlaşılabilir hale getirdiğini fark ettim - her zaman bir çeşit döngü. Finansal tablolar gibi Python'un acemi kullanıcı için tasarlanmadığını, eğitim almak isteyen kullanıcı için tasarlandığını da fark ettim. Bu dilin ne kadar güçlü olduğuna inanamıyorum. Bana (sonunda) lambdaların amacını ve değerini ortaya çıkardığında, yaklaşık 30 programı yırtıp, uygun yerlerde lambdas koymaya başlamak istedim.


5

Lambda kullanmak için yararlı bir durum , uzun liste kavramalarının okunabilirliğini arttırmaktır . Bu örnekte loop_dicnetlik kısadır ancak loop_dicçok uzun olduğunu hayal edin . Sadece ibu değerin lambda sürümü yerine içeren düz bir değer kullanırsanız bir elde edersiniz 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'}]

Onun yerine

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

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

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

5

Size gerçekten lambda'ya ciddi ihtiyaç duyduğum bir örnek verebilirim. Kullanımın bir dosyayı sağ tıklayıp üç seçenekten birini atadığı bir grafik program yapıyorum. Tkinter'de (bunu yazdığım GUI arabirim programı), birisi bir düğmeye bastığında, argümanları alan bir komuta atanamayacağı ortaya çıkıyor. Seçeneklerden birini seçtiğimde ve seçimimin sonucunun olmasını istersem:

print 'hi there'

O zaman önemli değil. Ama ya belirli bir ayrıntıya sahip olmak için seçimime ihtiyacım olursa. Örneğin, A seçimini seçersem, A, B veya C seçimine bağlı bazı argümanlar alan bir işlevi çağırır, TKinter bunu destekleyemedi. Lamda aslında bunu atlatmak için tek seçenekti ...


2
Muhtemelen, belki def foo...de fooyerine geçebilirdin lambda. Bu sadece daha fazla kod ve bir isim bulmalısın.
Jon Coombs

4

Çoğunlukla boş bir nesne olarak veya parametreleri bir işleve kısmen bağlamak için oldukça sık kullanıyorum .

İşte örnekler:

null nesne modelini uygulamak için:

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

parametre bağlama için:

aşağıdaki API'ya sahip olduğumu varsayalım

def dump_hex(file, var)
    # some code
    pass

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

Sonra, hızlı bir şekilde alınan verileri bir dosyaya dökümü istemiyorum bunu:

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

4

kullanırım lambdaParametreleri içeren geri aramalar oluşturmak için . Aynı işlevselliği gerçekleştirmek için bir yöntem yazmaktan ziyade bir satırda bir lambda yazmak daha temizdir.

Örneğin:

import imported.module

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

aksine:

import imported.module

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

4

Ben bir python acemiyim, bu yüzden lambda hakkında net bir fikir edinmek için onu bir 'for' döngüsü ile karşılaştırdım; verimlilik açısından. İşte kod (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)

6
Değerleri timeitçıkarmaktan genellikle daha doğru sonuçlar veren modülle ilgilenebilirsiniz time.time().
Kevin

2
Hmm, birinci () ve ikinci () başlangıcında zamanlayıcıyı yeniden başlatmanız gerekmez mi?
qneill

2

Lambda bir prosedür kurucusudur. Programları çalışma zamanında sentezleyebilirsiniz, ancak Python'un lambda'sı çok güçlü değildir. Bu tür bir programlamayı çok az insanın anladığını unutmayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.