Lambda Pythona z podkreśleniem jako argument?

84

Co robi poniższy kod?

a = lambda _:True

Z tego, co przeczytałem i przetestowałem w interaktywnym monicie, wydaje się, że jest to funkcja, która zawsze zwraca True.

Czy dobrze to rozumiem? Mam nadzieję, że zrozumiem, dlaczego _użyto również podkreślenia ( ).

laycat
źródło
10
Dla tych, co jest lambda : True
bezparametrową lambdą
17
Coś Nie lubię o tym delegowania jest to, że tytułowe pytanie mówi o funkcji lambda „z NO zmiennych”, ale ciało pytanie i niemal wszystkie odpowiedzi, podać przykłady funkcji lambda o jednej zmiennej / argument. Że zmienna po prostu dzieje się mieć dziwną nazwę _, zamiast xlub aczy cokolwiek innego. Jeśli ktoś chce wiedzieć, jak napisać funkcję lambda, która nie przyjmuje argumentów; oto jak: określenie to tak: my_lambda = lambda : 255. Nazwij to tak: x = my_lambda()możesz zastąpić 255dowolną zwracaną wartością.
Wykałaczka Anemone
2
@ToothpickAnemone świetna odpowiedź! Obecnie najczęściej używam lambdy bez zmiennych do inicjowania defaultdicts. mam nadzieję, że będzie przydatny dla osób czytających ten wątek. ht = {} ht = defaultdict (lambda: 0, ht)
laycat

Odpowiedzi:

143

Nazwa _zmiennej is. Spróbuj. (Ta nazwa zmiennej jest zwykle nazwą ignorowanej zmiennej. Można powiedzieć, że jest to symbol zastępczy).

Pyton:

>>> l = lambda _: True
>>> l()
<lambda>() missing 1 required positional argument: '_'

>>> l("foo")
True

Więc ta lambda wymaga jednego argumentu . Jeśli chcesz lambda bez argumentu, która zawsze zwraca True, zrób to:

>>> m = lambda: True
>>> m()
True
winklerrr
źródło
7
@dopatraman przetestował to z Python 3.6.2under Mac OS 10.12i działa.
winklerrr,
6
Może mógłbyś dodać informację, że nazwa zmiennej _jest powszechnie używana, gdy sama zmienna nie jest naprawdę potrzebna. To jak „zmienna do wyrzucenia”, po prostu symbol zastępczy, który nie jest przydatny.
winklerrr,
1
@dopatraman W Ipythonie _ przechowuje wartość zwróconą przez ostatnie wyrażenie. Z tego powodu unikam używania _. stackoverflow.com/questions/17580289/…
Taro Kiritani
7

Podkreślenie to konwencja Pythona dotycząca nazwania nieużywanej zmiennej (np. Narzędzia do analizy statycznej nie zgłaszają jej jako nieużywanej zmiennej). W twoim przypadku argument lambda jest nieużywany, ale utworzony obiekt jest funkcją jednoargumentową, która zawsze zwraca True. Zatem twoja lambda jest nieco analogiczna do funkcji stałej w matematyce.

Łukasz Rogalski
źródło
to nie tylko konwersja do Pythona, to język agnostyczny, a podkreślenie służy do wskazania, że ​​zmienna jest tymczasowa lub nieistotna
Sławomir Lenart
6

wydaje się, że jest to funkcja, która mimo wszystko zwraca True.

Tak, jest to funkcja (lub lambda), która zwraca True. Podkreślenia , który jest zwykle zastępczy dla zmiennej ignorowany, jest konieczne w tym przypadku.

Przykład użycia takiej funkcji (która prawie nic nie robi):

dd = collections.defaultdict(lambda: True)

Gdy jest używany jako argument do defaultdict , możesz mieć Truejako ogólną wartość domyślną.

miku
źródło
4

Lambda oznacza funkcję. Powyższe stwierdzenie jest takie samo jak pisanie

def f(_):
    return True

Dla lambda musi istnieć zmienna. Więc przekazujesz mu zmienną o nazwie _(podobnie możesz przekazać x, y...)

hiady
źródło
3

Podkreślenie _jest prawidłowym identyfikatorem i jest tutaj używane jako nazwa zmiennej. Zawsze zwróci Trueargument przekazany do funkcji.

>>>a('123') 
True
haccks
źródło
Witam, dzięki za szybką odpowiedź. więc jest to anonimowa funkcja, która zawsze zwraca prawdę?
laycat
@laycat; Tak. To zawsze wróci prawda.
haccks
2

Poniżej znajduje się odpowiedni wiersz kodu:

a = lambda _:True

Tworzy funkcję mającą jeden parametr wejściowy: _. Podkreślenie to dość dziwny wybór nazwy zmiennej, ale to tylko nazwa zmiennej. Możesz używać _wszędzie, nawet jeśli nie używasz funkcji lambda. Na przykład zamiast ....

my_var = 5
print(my_var)

Możesz napisać:

_ = 5
print(_)

Był jednak powód, który _został użyty jako nazwa nazwy parametru zamiast czegoś w rodzaju xlub input. Za chwilę do tego dojdziemy.

Po pierwsze, musimy wiedzieć, że słowo kluczowe lambda konstruuje funkcję podobną do def, ale o innej składni. Definicja funkcji lambda a = lambda _:Truejest podobna do pisania:

def a(_):
    return True

Tworzy funkcję o nazwie az parametrem wejściowym _i zwraca True. Można by było równie łatwo napisać a = lambda x:True, xzamiast podkreślenia. Jednak konwencja jest taka, aby używać _jako nazwy zmiennej, gdy nie zamierzamy jej używać. Rozważ następujące:

for _ in range(1, 11):
    print('pear')

Zauważ, że indeks pętli nigdy nie jest używany w treści pętli. Chcemy po prostu, aby pętla wykonywała określoną liczbę razy. Jak winklerrrnapisano, „nazwa zmiennej _jest [...] jak„ zmienna do wyrzucenia ”, po prostu symbol zastępczy, który nie jest użyteczny”.

Podobnie w przypadku `` a = lambda x: True '' parametr wejściowy nie jest używany w treści funkcji. Tak naprawdę nie ma znaczenia, jaki jest argument wejściowy, o ile istnieje. Autor tej funkcji lambda napisał _zamiast czegoś podobnego x, aby wskazać, że zmienna nie zostanie użyta.

Zauważ, że lambda nie ma argumentu; Więc piszę

a(), spowoduje błąd.

Jeśli chcesz lambda bez argumentu, napisz coś takiego:

 bar = lambda: True

Teraz dzwonienie bar()bez argumentów będzie działać dobrze. Lambda, która nie przyjmuje argumentów, nie musi zawsze zwracać tę samą wartość:

import random
process_fruit = lambda : random.random()

Powyższa funkcja lambda jest bardziej złożona niż coś, co zawsze zwraca tę samą stałą.

Jednym z powodów, dla których programiści czasami używają lambdasłowa kluczowego zamiast słowa, def są funkcje, które są szczególnie krótkie i proste. Zwróć uwagę, że lambdadefinicja zazwyczaj mieści się w jednym wierszu, podczas gdy trudno jest zrobić to samo z instrukcją def. Kolejny powód, aby użyć lambdazamiast defsf, gdy funkcja nie będzie ponownie używana. Jeśli nie chcemy później ponownie wywoływać funkcji, nie ma potrzeby nadawania jej nazwy. Weźmy na przykład pod uwagę następujący kod:

def apply_to_each (transform, in_container): out_container = list () for idx, item in enumerate (container, 0): out_container [idx] = transform (item) return out_container

Teraz wykonujemy następujące wezwanie:

squares  = apply_to_each(lambda x: x**2 range(0, 101))

Zauważ, że lambda x: x**2nie ma etykiety. Dzieje się tak, ponieważ prawdopodobnie nie zadzwonimy do tego ponownie później, było to coś krótkiego i prostego, czego potrzebowaliśmy tymczasowo.

Fakt, że funkcjom lambda nie trzeba nadawać nazwy, jest źródłem innej nazwy, która je opisuje: „funkcje anonimowe”.

Zauważ również, że instrukcje lambda są jak wywołanie funkcji, ponieważ zwracają referencję do funkcji, którą tworzą. Następujące jest nielegalne:

apply_to_each(def foo(x): x**2 ,  range(0, 101))

Podczas gdy apply_to_each(lambda x: x**2 range(0, 101))jest w porządku.

Tak więc używamy lambdazamiast defi _zamiast długiej nazwy zmiennej, gdy chcemy czegoś krótkiego, słodkiego i prawdopodobnie nie będziemy chcieli użyć go później.

IdleCustard
źródło