Czy ktoś może wyjaśnić konkretne powody, dla których BDFL decyduje się na utworzenie pojedynczej linii dla lambda Python?
To jest dobre:
lambda x: x**x
Powoduje to błąd:
lambda x:
x**x
Rozumiem, że stworzenie wieloliniowej linii lambda „zakłóciłoby” normalne zasady wcięć i wymagałoby dodania kolejnych wyjątków, ale czy nie jest to warte korzyści?
Spójrz na przykład na JavaScript. Jak żyć bez tych anonimowych funkcji? Są niezbędne. Czy Pythoniści nie chcą pozbyć się konieczności nazywania każdej funkcji wieloliniowej tylko po to, aby przekazać ją jako argument?
def
? Ma teraz dokładnie taką samą strukturę wizualną.Odpowiedzi:
Guido van van Rossum sam odpowiedział na to:
http://www.artima.com/weblogs/viewpost.jsp?thread=147358
Zasadniczo mówi, że chociaż możliwe jest rozwiązanie, nie jest ono zgodne z tym, jak Python jest.
źródło
doskonale jest wykonywać wieloliniową lambda w pythonie: patrz
prawdziwym ograniczeniem lambda jest fakt, że lambda musi być pojedynczym wyrażeniem ; nie może zawierać słowa kluczowego (jak python2
print
lubreturn
).GvR decyduje się to zrobić, aby ograniczyć rozmiar lambda, ponieważ zwykle są one używane jako parametry. Jeśli chcesz prawdziwą funkcję, użyj
def
źródło
def
. Pomyśl o tym: naprawdę potrzebujesz wywoływalnego parametru jako parametru swojej funkcji? I użytkownicy tej funkcji nie mogą przekazać swoją domyślną wymagalne? Jak mogą je przekazać, jeśli im nie dasz?Wiem, że to jest bardzo stare, ale umieszczam tutaj jako odniesienie.
Alternatywą dla zastosowania lambda może być użycie
def
w niekonwencjonalny sposób. Celem jest przekazaniedef
funkcji, która może być wykonana tylko w jednej sytuacji - dekoratora. Zauważ, że dzięki tej implementacjidef result
nie tworzona jest funkcja, lecz wynikreduce()
, który kończy się nadict
.Bezwstydna wtyczka : robię dużo tego tutaj .
Zauważ, że lambd z wieloma wyrażeniami można zrobić, ale tylko z naprawdę, naprawdę brzydkim kodem. Interesujące jest jednak to, w jaki sposób scoping działa z tą implementacją (zwróć uwagę na wielokrotne użycie
name
zmiennej i zacienianiemessage
zmiennej).źródło
Zebranie razem lambda z wieloma wyrażeniami nie jest tak złe, jak się wydaje pirospada: pewnie moglibyśmy skomponować kilka funkcji monadycznych za pomocą binda, jak w Haskell, ale skoro jesteśmy w nieczystym świecie Pythona, równie dobrze możemy użyj efektów ubocznych, aby osiągnąć to samo.
Na moim blogu opisuję kilka sposobów, aby to zrobić .
Na przykład Python gwarantuje, że elementy krotki będą oceniane w kolejności, dzięki czemu możemy używać
,
podobnie jak imperatywu;
. Możemy zastąpić wieleprint
wyrażeń, takich jak , wyrażeniami, takimi jaksys.stdout.write
.Dlatego następujące są równoważne:
Zauważ, że dodałem
None
na końcu i wyodrębniłem go za pomocą[-1]
; ustawia to wyraźnie wartość zwracaną. Nie musimy tego robić, ale bez tego uzyskalibyśmy funky(None, None, None)
wartość zwrotną, o którą moglibyśmy dbać lub nie.Możemy więc sekwencjonować działania IO. Co ze zmiennymi lokalnymi?
Python
=
tworzy zdanie, więc musimy znaleźć równoważne wyrażenie. Jednym ze sposobów jest mutowanie zawartości struktury danych, przekazywanej jako argument. Na przykład:Jest kilka sztuczek używanych w
stateful_lambda
:*_
Argument umożliwia naszym lambda podjąć jakąkolwiek liczbę argumentów. Ponieważ pozwala to na zerowe argumenty, odzyskujemy konwencję wywoływania zstateful_def
._
to tylko konwencja, która mówi: „Nie zamierzam używać tej zmiennej”lambda state: lambda *_: ...
(lambda state: ...)({})
state
do wartości{}
bez użycia instrukcji przypisania (np.state = {}
)state
jak nazwy zmiennych i wartości powiązanestate.setdefault(a, b)
zamiasta = b
istate.get(a)
zamiasta
[-1]
do wyodrębnienia ostatniej wartości, która działa jakreturn
instrukcjaOczywiście jest to dość kłopotliwe, ale możemy stworzyć ładniejszy interfejs API z funkcjami pomocniczymi:
źródło
Myślałem, że mógłbym się przyłączyć, użyć przerywacza linii:
Nie zapominaj o bardzo miłej rzeczy, jaką Python potrafi pisać oneliner, jak na przykład:
I lambda jest bardzo potężna, ale nie jest przeznaczona do zastąpienia 1 całej funkcji, to znaczy możesz ją zhakować (przykład pożyczenia od kolegi powyżej):
Ale czy naprawdę chcesz to zrobić w ten sposób? Po pewnym czasie jest to w większości nieczytelne, to jak dotarcie do początku liny, zaczynając od nierozwiniętego końca.
Lambdas są traktowane jako funkcje jednorazowe, w mapowaniu, filtrowaniu i zmniejszaniu funkcji w funkcyjnym programowaniu (między innymi). Na przykład uzyskanie wartości znakowych wartości, które są liczbami całkowitymi i podzielnymi przez 2
Możesz użyć go jako funkcji wyrażania funkcji, definiując złożoną funkcję (lub więcej i kilka lambd, i umieszczając ją w innej lambda:
ale Python ma obsługę wyrażeń funkcji w inny sposób: -lets mówi, że masz wywoływaną funkcję
superAwesomeFunction
i że ta funkcja może robić super niesamowite rzeczy, możesz przypisać ją do zmiennej, nie wywołując jej, tak jak to:Więc teraz, gdy wywołasz SAF, wywołasz superAwesomeFunction lub metodę. Jeśli przeszukujesz folder Lib, możesz zauważyć, że większość
__builtin__
modułów Pythona jest napisana w ten sposób. Dzieje się tak, ponieważ czasami będziesz potrzebować niektórych funkcji, które wykonują określone zadania, które nie są wystarczająco potrzebne, aby były użyteczne dla użytkownika, ale są niezbędne dla kilku funkcji. Zatem masz wybór, że nie możesz mieć 2 funkcji o nazwie „superAwesomeFunction”, możesz mieć „superAwesomeFunctionDoingBasicStuf” i „realSuperAwesomeFunction”, a następnie po prostu wstawić „realSuperAwesomeFunction” w zmiennej „superAwesomeFunction” i gotowe.Możesz znaleźć lokalizację zaimportowanych modułów, wchodząc do konsoli
importedModule.__file__
(prawdziwy przykładimport os;os.__file__
), i po prostu podążaj za tym katalogiem do pliku o nazwie importModule.py i otwórz go w edytorze i dowiedz się, jak zmaksymalizować własną „wiedzę”.Mam nadzieję, że to pomoże tobie i innym współpracownikom w tarapatach.
źródło