Hangisinin kullanılması daha çok tercih edilir: lambda fonksiyonları mı yoksa iç içe geçmiş fonksiyonlar ('def') mı?


104

Çoğunlukla lambda işlevlerini kullanıyorum, ancak bazen aynı davranışı sağlayan iç içe geçmiş işlevler kullanıyorum.

Burada, eğer biri başka bir işlevde bulunursa, aynı şeyi işlevsel olarak yaptıkları bazı önemsiz örnekler verilmiştir:

Lambda işlevi

>>> a = lambda x : 1 + x
>>> a(5)
6

İç içe geçmiş işlev

>>> def b(x): return 1 + x

>>> b(5)
6

Birini diğerine göre kullanmanın avantajları var mı? (Performans? Okunabilirlik? Sınırlamalar? Tutarlılık? Vb.)

Fark eder mi? Aksi takdirde, bu Pythonic prensibini ihlal eder:

Bunu yapmanın bir ve tercihen tek bir açık yolu olmalıdır .

Yanıtlar:


108

lambdaBir isme atamanız gerekiyorsa , defbunun yerine a kullanın. defs sadece bir ödev için sözdizimsel şekerlerdir, dolayısıyla sonuç aynıdır ve çok daha esnek ve okunabilirdir.

lambdas bir kez kullanılmak üzere kullanılabilir, adı olmayan işlevleri atabilirsiniz .

Ancak bu kullanım durumu çok nadirdir. Adsız işlev nesnelerini nadiren dolaşmanız gerekir.

Yerleşikler map()ve filter()ihtiyaç duyulan işlev nesneleri, ancak liste anlamaları ve üreteç ifadeleri genellikle bu işlevlerden daha okunabilirdir ve lambdalara ihtiyaç duymadan tüm kullanım durumlarını kapsayabilir.

Gerçekten küçük bir işlev nesnesine ihtiyaç duyduğunuz durumlarda, operatormodül işlevlerini kullanmalısınız , örneğin operator.add:lambda x, y: x + y

Hala lambdaele alınmayanlara ihtiyacınız varsa def, daha okunaklı olması için bir yazmayı düşünebilirsiniz . İşlev operatormodüldekilerden daha karmaşıksa , a defmuhtemelen daha iyidir.

Dolayısıyla, gerçek dünyada iyi lambdakullanım durumları çok nadirdir.


10
Ben ne zaman kullanılacağına ilişkin yanıta katılabilir lambda, ama bu "çok nadir" olduğunu katılmıyorum, bu anahtar fonksiyonları için yaygındır sortedya itertools.groupbyvs. meselasorted(['a1', 'b0'], key= lambda x: int(x[1]))
Chris_Rands

31

Pratik olarak bana göre iki fark var:

İlki, ne yaptıkları ve ne geri döndükleri ile ilgili:

  • def, hiçbir şey döndürmeyen ve yerel ad alanında bir 'ad' oluşturan bir anahtar sözcüktür.

  • lambda, bir işlev nesnesi döndüren ve yerel ad alanında bir 'ad' oluşturmayan bir anahtar sözcüktür.

Bu nedenle, bir işlev nesnesi alan bir işlevi çağırmanız gerekiyorsa, bunu bir satır python kodunda yapmanın tek yolu lambda kullanmaktır. Def ile eşdeğeri yoktur.

Bazı çerçevelerde bu aslında oldukça yaygındır; örneğin, Twisted'ı çok kullanıyorum ve böyle bir şey yapıyorum

d.addCallback(lambda result: setattr(self, _someVariable, result))

oldukça yaygındır ve lambdalar ile daha özlüdür.

İkinci fark, gerçek işlevin ne yapmasına izin verildiğiyle ilgilidir.

  • 'Def' ile tanımlanan bir işlev herhangi bir python kodunu içerebilir
  • 'Lambda' ile tanımlanan bir işlev bir ifade olarak değerlendirilmelidir ve bu nedenle print, import, boost, ... gibi ifadeler içeremez.

Örneğin,

def p(x): print x

beklendiği gibi çalışır

lambda x: print x

bir SyntaxError'dır.

Elbette, geçici çözümler var - printile sys.stdout.writeveya importile değiştirin __import__. Ancak bu durumda genellikle bir işleve gitmeniz daha iyidir.


23

Bu röportajda Guido van Rossum, Python'a 'lambda'nın girmesine izin vermemesini dilediğini söylüyor:

" S. Python'un hangi özelliğinden en az memnunsunuz?

Bazen katkıları kabul etmekte çok hızlı davrandım ve daha sonra bunun bir hata olduğunu anladım. Lambda fonksiyonları gibi işlevsel programlama özelliklerinden bazıları buna bir örnek olabilir. Lambda küçük bir anonim işlev oluşturmanıza izin veren bir anahtar sözcüktür; eşleme, filtreleme ve azaltma gibi yerleşik işlevler, liste gibi bir dizi türü üzerinde bir işlevi çalıştırır.

Pratikte o kadar da iyi gitmedi. Python'un yalnızca iki kapsamı vardır: yerel ve genel. Bu, lambda işlevlerini yazmayı zahmetli hale getirir, çünkü genellikle lambda'nın tanımlandığı kapsamdaki değişkenlere erişmek istersiniz, ancak iki kapsam nedeniyle bunu yapamazsınız. Bunun bir yolu var, ama bu biraz karışık. Python'da genellikle lambda işlevleriyle uğraşmak yerine sadece bir for döngüsü kullanmak çok daha kolay görünür. harita ve arkadaşlar, yalnızca istediğinizi yapan yerleşik bir işlev olduğunda iyi çalışır.

IMHO, Iambdas bazen uygun olabilir, ancak genellikle okunabilirlik pahasına uygundur. Bunun ne yaptığını bana söyleyebilir misin:

str(reduce(lambda x,y:x+y,map(lambda x:x**x,range(1,1001))))[-10:]

Yazdım ve anlamam bir dakikamı aldı. Bu Project Euler'den - spoilerlardan nefret ettiğim için hangi problemi söylemeyeceğim ama 0.124 saniyede çalışıyor :)


20
Röportajın oldukça eski olduğunu ve Python'un uzun zamandır iç içe geçmiş kapsamlar eklediğini ve bu da lambda'ya karşı verdiği argümanın artık alakasız hale geldiğini unutmayın. Eminim hala lambda için pişmanlık duymaktadır, ancak Python 3.0'da onu kaldırmak için yeterli değildir.
Thomas Wouters

10
Gerçekten örneğiniz, lambdalara değil, tek satırlıklara karşı bir argüman olmalıdır. Ayrıca, lambda: str (toplam (harita (lambda x: x ** x, aralık (1001)))) [: - 10]
Triptych

2
@ThomasWouters: lambda3.0'da kaldırılmamanın yakın bir şey olduğunu ve Guido'nun onu korumak için savaşmadığını anlıyorum.
Ethan Furman

11

N = 1000 için işte biraz zamanBir işlevi lambda'ya karşı çağırmanın zamanı:

In [11]: def f(a, b):
             return a * b

In [12]: g = lambda x, y: x * y

In [13]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    f(a, b)
   ....:
100 loops, best of 3: 285 ms per loop

In [14]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    g(a, b)
   ....:
100 loops, best of 3: 298 ms per loop

In [15]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    (lambda x, y: x * y)(a, b)
   ....:
100 loops, best of 3: 462 ms per loop

3
Lambda ve tanımlı sürümlerin kabaca eşdeğer olduğunu görmek ilginç. Son test daha fazla zaman aldı çünkü python, lambda işlevini her tanımladığında muhtemelen alan ayırması gerekiyordu.
hlin117

Sanırım bu mantıklı çünkü tanım yerel değişkenlere gönderme yapıyor olabilir (ki bu değişmiş olabilir) ... buradaki gibi olmadığı durumda cpython daha iyi bir iş çıkarabilir.
Andy Hayden

Dis.dis kullanın; (Lambda x, y: x * y) her döngüde işlevi yaratır. Lambda'yı döngüden önce oluşturursanız (diğer adıyla f = lambda x, y: x * y), işlevi çağırmak için bayt kodu önceki örneğinizdeki g / f ile tam olarak aynı olacaktır, bu nedenle lambda performansı aynıdır def işlevi olarak. Aynı şekilde kullanırsanız, lambda veya def etkisi yok. Tersini yapın, döngü içinde f () işlevini bildirin, sonra çağırın ...
tito

@tito 3 zamanlı örneğin gösterdiği şeyin tam olarak bu olduğuna inanıyorum ...
Andy Hayden

@tito oh, döngüdeki işlevi tanımladığını söylüyorsun, elbette, ama bunun alışılmadık bir model olduğunu iddia ediyorum. Bunun neden bu yoruma olumsuz oy vermesi gerektiğinden emin değilim ...
Andy Hayden

7

Verim:

İçeren işlev oluşturma lambdaolduğunu biraz daha hızlı olan oluştururken daha def. Aradaki fark, defyereller tablosunda bir ad girişi oluşturmaktan kaynaklanmaktadır . Ortaya çıkan işlev aynı yürütme hızına sahiptir.


Okunabilirlik:

Lambda işlevleri çoğu Python kullanıcısı için biraz daha az okunabilir, ancak bazı durumlarda çok daha özlüdür. İşlevsel olmayan rutinden işlevsel rutine dönüştürmeyi düşünün:

# Using non-functional version.

heading(math.sqrt(v.x * v.x + v.y * v.y), math.atan(v.y / v.x))

# Using lambda with functional version.

fheading(v, lambda v: math.sqrt(v.x * v.x + v.y * v.y), lambda v: math.atan(v.y / v.x))

# Using def with functional version.

def size(v):
    return math.sqrt(v.x * v.x + v.y * v.y)

def direction(v):
    return math.atan(v.y / v.x)

deal_with_headings(v, size, direction)

Gördüğünüz gibi, işlevsel sürüme dönüştürmek için lambdayalnızca lambda v:orijinal işlevsel olmayan sürüme eklemeniz gerekmesi açısından sürüm daha kısa ve "daha kolay" . Aynı zamanda çok daha özlü. Ancak unutmayın, birçok Python kullanıcısı lambda sözdizimi ile karıştırılacaktır, bu nedenle uzunluk ve gerçek karmaşıklıkta kaybettiğiniz şey, diğer kodlayıcıların kafa karışıklığı içinde geri kazanılabilir.


Sınırlamalar:

  • lambda işlevler, bir değişken adına atanmadıkça yalnızca bir kez kullanılabilir.
  • lambdadeğişken adlarına atanan işlevlerin işlevlere göre hiçbir avantajı yoktur def.
  • lambda fonksiyonların toplanması zor veya imkansız olabilir.
  • def işlevlerin adları, makul ölçüde açıklayıcı ve benzersiz olacak veya en azından kapsam açısından kullanılmayacak şekilde dikkatlice seçilmelidir.

Tutarlılık:

Python, prosedürel ve daha basit nesnel anlambilim lehine çoğunlukla işlevsel programlama kurallarından kaçınır. lambdaOperatör bu önyargı doğrudan tezat teşkil ediyor. Dahası, halihazırda yaygın olana bir alternatif olarak def, lambdaişlev sözdiziminize çeşitlilik katar. Bazıları bunun daha az tutarlı olduğunu düşünür.


Önceden var olan işlevler:

Başkalarının da belirttiği gibi lambda, alandaki birçok kullanım , operatorveya diğer modüllerin üyeleri ile değiştirilebilir . Örneğin:

do_something(x, y, lambda x, y: x + y)
do_something(x, y, operator.add)

Önceden var olan işlevi kullanmak, çoğu durumda kodu daha okunaklı hale getirebilir.


Pythonic ilkesi: "Bunu yapmanın bir ve tercihen yalnızca bir - bariz bir yolu olmalıdır"

Bu , doğruluk doktrininin tek kaynağına benzer . Ne yazık ki, tek-apaçık-yap-yapma-yolu ilkesi, gerçek bir yol gösterici ilkeden ziyade, her zaman Python için hüzünlü bir özlem olmuştur. Python'daki çok güçlü dizi anlayışlarını düşünün. İşlevsel olarak mapve filterişlevlerine eşdeğerdirler :

[e for e in some_array if some_condition(e)]
filter(some_array, some_condition)

lambdave defaynı.

Bu bir fikir meselesi, ancak Python dilinde genel kullanım için tasarlanmış ve herhangi bir şeyi açıkça bozmayan herhangi bir şeyin yeterince "Pythonic" olduğunu söyleyebilirim.


7

Daha çok tercih edilen: lambda işlevleri mi yoksa yuvalanmış işlevler ( def) mi?

Normal bir işleve göre bir lambda kullanmanın bir avantajı vardır: bir ifadede yaratılırlar.

Birkaç dezavantaj var:

  • isim yok (sadece '<lambda>')
  • belge yok
  • ek açıklama yok
  • karmaşık ifade yok

Ayrıca ikisi de aynı tür nesnedir. Bu nedenlerden dolayı, genellikle deflambdas yerine anahtar kelimeyle işlevler oluşturmayı tercih ederim .

İlk nokta - bunlar aynı tür nesneler

Bir lambda, normal bir işlevle aynı türde nesne ile sonuçlanır

>>> l = lambda: 0
>>> type(l)
<class 'function'>
>>> def foo(): return 0
... 
>>> type(foo)
<class 'function'>
>>> type(foo) is type(l)
True

Lambdalar işlev olduklarından birinci sınıf nesnelerdir.

Hem lambdalar hem de işlevler:

  • bir argüman olarak aktarılabilir (normal bir fonksiyonla aynı)
  • bir dış işlev içinde oluşturulduğunda, bu dış işlevlerin yerelleri üzerinde bir kapanış haline gelir

Ancak lambdalar, varsayılan olarak, işlevlerin tam işlev tanımı sözdizimi yoluyla elde ettiği bazı şeyleri kaçırır.

Bir Lamba adlı __name__is'<lambda>'

Sonuçta Lambdalar anonim işlevlerdir, bu nedenle kendi adlarını bilmiyorlar.

>>> l.__name__
'<lambda>'
>>> foo.__name__
'foo'

Böylece, lambda'lar ad alanlarında programlı olarak aranamaz.

Bu, belirli şeyleri sınırlar. Örneğin, fooserileştirilmiş kodla aranabilir, ancak şunlar lyapılamaz:

>>> import pickle
>>> pickle.loads(pickle.dumps(l))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <function <lambda> at 0x7fbbc0464e18>: 
attribute lookup <lambda> on __main__ failed

fooGayet iyi arayabiliriz - çünkü kendi adını biliyor:

>>> pickle.loads(pickle.dumps(foo))
<function foo at 0x7fbbbee79268>

Lambdaların ek açıklaması ve belge dizesi yoktur

Temel olarak, lambdalar belgelenmemiştir. fooDaha iyi belgelenmek için yeniden yazalım :

def foo() -> int:
    """a nullary function, returns 0 every time"""
    return 0

Şimdi, foo'nun belgeleri var:

>>> foo.__annotations__
{'return': <class 'int'>}
>>> help(foo)
Help on function foo in module __main__:

foo() -> int
    a nullary function, returns 0 every time

Oysa aynı bilgiyi lambdalara vermek için aynı mekanizmaya sahip değiliz:

>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda (...)

Ama onları hackleyebiliriz:

>>> l.__doc__ = 'nullary -> 0'
>>> l.__annotations__ = {'return': int}
>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda ) -> in
    nullary -> 0

Ancak muhtemelen yardımın çıktısını bozan bazı hatalar vardır.

Lambdas yalnızca bir ifade döndürebilir

Lambdas karmaşık ifadeler döndüremez, yalnızca ifadeler.

>>> lambda: if True: 0
  File "<stdin>", line 1
    lambda: if True: 0
             ^
SyntaxError: invalid syntax

İfadeler kuşkusuz oldukça karmaşık olabilir ve çok çabalarsanız, muhtemelen aynısını bir lambda ile de başarabilirsiniz, ancak eklenen karmaşıklık, açık kod yazmaya daha çok zarar verir.

Netlik ve sürdürülebilirlik için Python kullanıyoruz. Lambdaların aşırı kullanımı buna karşı çalışabilir.

Sadece lambdas için baş: Tek bir ifadede oluşturulabilir

Bu mümkün olan tek olumlu yöndür. İfade ile bir lambda yaratabildiğiniz için, onu bir fonksiyon çağrısı içinde yaratabilirsiniz.

Bir işlev çağrısı içinde bir işlev oluşturmak, başka bir yerde oluşturulan ad aramasına karşı (ucuz) ad aramasını önler.

Bununla birlikte, Python katı bir şekilde değerlendirildiğinden, bunu yapmanın ad aramasından kaçınmanın dışında başka bir performans kazanımı yoktur.

Çok basit bir ifade için bir lambda seçebilirim.

Ayrıca etkileşimli Python yaparken, biri yapacağı zaman birden fazla satırdan kaçınmak için lambdas kullanma eğilimindeyim. Çağırırken bir yapıcıya bir bağımsız değişken geçirmek istediğimde aşağıdaki kod biçimini kullanıyorum timeit.repeat:

import timeit

def return_nullary_lambda(return_value=0):
    return lambda: return_value

def return_nullary_function(return_value=0):
    def nullary_fn():
        return return_value
    return nullary_fn

Ve şimdi:

>>> min(timeit.repeat(lambda: return_nullary_lambda(1)))
0.24312214995734394
>>> min(timeit.repeat(lambda: return_nullary_function(1)))
0.24894469301216304

Yukarıdaki küçük zaman farkının, isim aramasına atfedilebileceğine inanıyorum return_nullary_function- çok önemsiz olduğunu unutmayın .

Sonuç

Lambdalar, tek bir noktaya değinmek için kod satırlarını en aza indirmek istediğiniz gayri resmi durumlar için iyidir.

Lambdalar, özellikle önemsiz olmadıkları durumlarda, daha sonra gelecek olan kod editörleri için açıklığa ihtiyaç duyduğunuz daha resmi durumlar için kötüdür.

Nesnelerimize güzel isimler vermemiz gerektiğini biliyoruz. Nesne sahip olduğunda nasıl bunu yapabilirler hiçbir ad?

Tüm bu nedenlerden dolayı genellikle with defyerine ile işlevler oluşturmayı tercih ediyorum lambda.


6

Nosklo'nun tavsiyesine katılıyorum: işleve bir ad vermeniz gerekiyorsa, kullanın def. Ben rezerve lambdasadece başka işlevi, örneğin kod kısa bir özeti geçiyorum durumlar için işlevler:

a = [ (1,2), (3,4), (5,6) ]
b = map( lambda x: x[0]+x[1], a )

3
Çoğu map / lambda kombinasyonunda, onu bir liste kavrama veya daha uygun işlevle değiştirebilirsiniz. Örneğin, "harita (toplam, a)" veya "[x [0] + x [1] x in a] için"
John Millikin

Evet bu doğru. Bazen haritayı () tercih ederim. Bu çoğunlukla bir satır içi işlevi kullanmanın yapmacık bir örneğiydi.
Dan Lenski

tam olarak ... Çoğu örnek uydurmadır, çünkü kullanımı doğal değildir ve çoğu durumda pratik daha iyi yollar vardır.
nosklo

5

Diğer cevaplara katılırken, bazen daha okunabilir. lambdaN boyutuyla sürekli karşılaştığım bir kullanım durumunda burada kullanışlı olan bir örnek var defaultdict.
İşte bir örnek:

from collections import defaultdict
d = defaultdict(lambda: defaultdict(list))
d['Foo']['Bar'].append(something)

defİkinci boyut için bir oluşturmaktan daha okunaklı buluyorum . Bu, daha yüksek boyutlar için daha da önemlidir.


from functools import partial; defaultdict(partial(defaultdict, list)). Bir kereden fazla kullanmak istiyorsanız, kısmi bir ada atayın. Ancak, bu yapıyla karşılaşmaya devam ederseniz, KURU olmadığınız anlamına gelir. Bunu bir yardımcı program kitaplığına çarpın. Bu yapıyı, diğer işlev araçlarını (veya bir döngü veya özyineleme) kullanarak rastgele bir n boyutlu defaultdict oluşturmak için kullanabilirsiniz.
DylanYoung

3

Lambda'nın birincil kullanımı her zaman basit geri çağırma işlevleri ve bağımsız değişken olarak bir işlev gerektiren eşleme, azaltma, filtreleme için olmuştur. Liste anlayışlarının norm haline gelmesiyle ve aşağıdakiler gibi eklendiğinde izin verilir:

x = [f for f in range(1, 40) if f % 2]

günlük kullanımda lambda kullanımı için gerçek bir durum hayal etmek zor. Sonuç olarak, lambda'dan kaçının ve iç içe geçmiş işlevler oluşturun derim.


3

Lambdaların önemli bir sınırlaması, bir ifade dışında hiçbir şey içerememeleridir. Bir lambda ifadesinin önemsiz yan etkilerin yanı sıra herhangi bir şey üretmesi neredeyse imkansızdır, çünkü bir defişlev kadar zengin bir vücuda sahip olamaz .

Bununla birlikte Lua, programlama tarzımı anonim işlevlerin kapsamlı kullanımına doğru etkiledi ve kodumu onlarla birlikte doldurdum. Bunun da ötesinde, haritayı soyut operatörler olarak, liste anlamalarını veya oluşturucuları düşünmediğim şekillerde düşünme eğilimindeyim, neredeyse bu operatörleri kullanarak bir uygulama kararını açıkça erteliyormuşum gibi.

Düzenleme: Bu oldukça eski bir soru ve konuyla ilgili görüşlerim biraz değişti.

Öncelikle, lambdabir değişkene bir ifade atamaya şiddetle karşı çıkıyorum ; python sadece bunun için özel bir sözdizimine sahiptir (ipucu, def). Buna ek olarak, bir isim almadıklarında bile lambda için kullanılan birçok kullanım önceden tanımlanmış (ve daha verimli) uygulamalara sahiptir. Örneğin, söz konusu örnek (1).__add__, a lambdaveya ile sarmaya gerek kalmadan sadece olarak kısaltılabilir def. Diğer pek çok yaygın kullanım operator, itertoolsve functoolsmodüllerinin bazı kombinasyonlarıyla tatmin edilebilir .


1
(1).__add__- dunder yöntemlerini doğrudan çağırmak neredeyse hiç olmamalıdır. lambdaHer direkt dunder çağrısı için bin saniye.
Ethan Furman

1
@EthanFurman: Benim deneyimlerime göre, doğanın çağrıları (1).__add__pek alışılmadık bir durum, ama "gerekir" e yakın bir yere gitmem. Şüphesiz, ilkini çok daha okunaklı buluyorum lambda x: 1 + x. Haskells dilim gösterimine daha benzer bir şeyimiz (1+)olsaydı , bu harika olurdu, ama anlamsal olarak tam olarak o şey olan dunder yöntemi adıyla bir idare etmeliyiz.
SingleNegationElimination

2
  • Hesaplama süresi.
  • İsimsiz işlev.
  • Tek işlev ve birçok kullanım işlevine ulaşmak için.

Basit bir örnek olarak,

# CREATE ONE FUNCTION AND USE IT TO PERFORM MANY OPERATIONS ON SAME TYPE OF DATA STRUCTURE.
def variousUse(a,b=lambda x:x[0]):
    return [b(i) for i in a]

dummyList = [(0,1,2,3),(4,5,6,7),(78,45,23,43)]
variousUse(dummyList)                           # extract first element
variousUse(dummyList,lambda x:[x[0],x[2],x[3]]) # extract specific indexed element
variousUse(dummyList,lambda x:x[0]+x[2])        # add specific elements
variousUse(dummyList,lambda x:x[0]*x[2])        # multiply specific elements

1

Lambda'yı yerel kapsamdaki bir değişkene atayacaksanız, daha okunabilir olduğu ve gelecekte daha kolay genişletilebileceği için def'i de kullanabilirsiniz:

fun = lambda a, b: a ** b # a pointless use of lambda
map(fun, someList)

veya

def fun(a, b): return a ** b # more readable
map(fun, someList)

Her ikisi de from operator import pow;map(pow, someList)ve (a**b for a,b in someList)daha da okunabilir.
InQβ

1

Bulduğum lambdalar için bir kullanım ... hata ayıklama mesajlarında.

Lambdalar tembel olarak değerlendirilebildiği için aşağıdaki gibi kodlara sahip olabilirsiniz:

log.debug(lambda: "this is my message: %r" % (some_data,))

muhtemelen pahalı yerine:

log.debug("this is my message: %r" % (some_data,))

hata ayıklama çağrısı geçerli günlük kaydı seviyesi nedeniyle çıktı üretmese bile biçim dizesini işler.

Tabii ki bunun açıklandığı gibi çalışması için, kullanımdaki günlükleme modülü lambdaları "tembel parametreler" olarak desteklemelidir (günlük modülümün yaptığı gibi).

Aynı fikir, isteğe bağlı içerik değeri yaratmaya yönelik diğer herhangi bir tembel değerlendirme durumuna da uygulanabilir.

Örneğin bu özel üçlü operatör:

def mif(condition, when_true, when_false):
    if condition:
         return when_true()
    else:
         return when_false()

mif(a < b, lambda: a + a, lambda: b + b)

onun yerine:

def mif(condition, when_true, when_false):
    if condition:
         return when_true
    else:
         return when_false

mif(a < b, a + a, b + b)

lambdas ile yalnızca koşul tarafından seçilen ifade değerlendirilir, lambdas olmadan her ikisi de değerlendirilir.

Elbette lambdalar yerine işlevleri kullanabilirsiniz, ancak kısa ifadeler için lambdalar (c) daha zayıftır.


1
NB loggingzaten geç biçimlendirmeye sahiptir: log.debug("this is my message: %r", some_data)yalnızca mesaj istendiğinde / olduğunda biçimlendirir .
j08lue

@ j08lue lambda yöntemi, hata ayıklama çıktısının üretilmemesi durumunda her şeyin değerlendirilmesini atlar, gösterdiğiniz durumda some_datapahalı bir ifade veya işlev / yöntem çağrısı olabilir.
Glushiator

0

Nosklo'ya katılıyorum. Bu arada, bir kez kullansanız bile , atma işlevi, çoğu zaman sadece operatör modülünden bir şey kullanmak istersiniz.

ÖRNEĞİN :

Bu imzaya sahip bir işleviniz var: myFunction (veri, geri arama işlevi).

2 öğe ekleyen bir işlevi geçmek istiyorsunuz.

Lambda kullanarak:

myFunction(data, (lambda x, y : x + y))

Pitonik yol:

import operator
myFunction(data, operator.add)

Veya elbette bu basit bir örnektir, ancak operatör modülünün sağladığı pek çok şey vardır, liste ve dikte için öğe belirleyiciler / alıcılar dahil. Gerçekten havalı.


-1

Önemli bir fark, defişlevlerin satır içi olarak kullanılamamasıdır ki bu benim görüşüme göre bir lambdaişlev için en uygun kullanım durumudur . Örneğin bir nesne listesini sıralarken:

my_list.sort(key=lambda o: o.x)

Bu nedenle, lambdaların bu tür önemsiz işlemler için kullanılmasını öneririm, bu da işlevin adlandırılmasıyla sağlanan otomatik belgelerden gerçekten fayda sağlamaz.


-2

lambda, yeni işlevler oluşturmak için kullanışlıdır:

>>> def somefunc(x): return lambda y: x+y
>>> f = somefunc(10)
>>> f(2)
12
>>> f(4)
14
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.