Otrzymuję to ostrzeżenie pep8 za każdym razem, gdy używam wyrażeń lambda. Czy wyrażenia lambda nie są zalecane? Jeśli nie to dlaczego?
Otrzymuję to ostrzeżenie pep8 za każdym razem, gdy używam wyrażeń lambda. Czy wyrażenia lambda nie są zalecane? Jeśli nie to dlaczego?
Odpowiedzi:
Zalecenia w PEP-8, na które się napotykasz, to:
Zawsze używaj instrukcji def zamiast instrukcji przypisania, która wiąże wyrażenie lambda bezpośrednio z nazwą.
Tak:
def f(x): return 2*x
Nie:
f = lambda x: 2*x
Pierwsza forma oznacza, że nazwą wynikowego obiektu funkcji jest konkretnie „f” zamiast ogólnego „<lambda>”. Jest to bardziej przydatne w przypadku śledzenia wstecznego i reprezentacji ciągów w ogóle. Zastosowanie instrukcji przypisania eliminuje jedyną korzyść, jaką wyrażenie lambda może zaoferować w stosunku do jawnej instrukcji def (tzn. Że można ją osadzić w większym wyrażeniu)
Przypisywanie lambdas do nazw w zasadzie powiela funkcjonalność def
- i ogólnie najlepiej zrobić coś w jeden sposób, aby uniknąć nieporozumień i zwiększyć przejrzystość.
Uzasadnionym przypadkiem użycia dla lambda jest miejsce, w którym chcesz użyć funkcji bez przypisania jej, np .:
sorted(players, key=lambda player: player.rank)
Zasadniczo głównym argumentem przeciwko temu jest to, że def
instrukcje spowodują powstanie większej liczby wierszy kodu. Moja główna odpowiedź na to brzmi: tak, i jest w porządku. O ile nie grasz w golfa, minimalizowanie liczby linii nie jest czymś, co powinieneś robić: idź na skróty.
def
sprawdzania PEP8 otrzymujesz E704 multiple statements on one line (def)
, a jeśli podzielisz ją na dwie linie, otrzymasz E301 expected 1 blank line, found 0
: - /
Oto historia, miałem prostą funkcję lambda, z której korzystałem dwa razy.
a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)
To tylko dla reprezentacji, spotkałem się z kilkoma różnymi wersjami tego.
Teraz, aby utrzymać stan NA SUCHO, zaczynam ponownie używać tej wspólnej lambda.
f = lambda x : x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
W tym momencie mój kontroler jakości kodu skarży się, że lambda jest nazwaną funkcją, więc przekształcam ją w funkcję.
def f(x):
return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
Teraz moduł sprawdzający skarży się, że funkcja musi być ograniczona jedną pustą linią przed i po.
def f(x):
return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
Tutaj mamy teraz 6 wierszy kodu zamiast oryginalnych 2 wierszy bez zwiększania czytelności i bez zwiększania pythoniczności. W tym momencie narzędzie do sprawdzania kodu skarży się, że funkcja nie ma dokumentów.
Moim zdaniem tej zasady lepiej unikać i łamać, gdy ma to sens, skorzystaj z własnego osądu.
a = [x + offset for x in simple_list]
. Nie musisz używać map
i lambda
tutaj.
x + offset
części do abstrakcyjnej lokalizacji, którą można zaktualizować bez zmiany więcej niż jednego wiersza kodu. Z listami, które już wspomniałeś, nadal potrzebujesz dwóch linii kodu, które zawierałyby x + offset
je teraz w listach. Aby wyciągnąć je tak, jak chciał autor, potrzebujesz def
lub lambda
.
def
i lambda
można również użyć funools.partial : f = partial(operator.add, offset)
a następnie a = list(map(f, simple_list))
.
def f(x): return x + offset
(tj. Prostą funkcją zdefiniowaną w jednym wierszu)? Przynajmniej z flake8 nie otrzymuję skarg na puste linie.
a, b = [[x + offset for x lst] for lst in (simple_list, another_simple_list)]
Lattyware ma absolutną rację: Zasadniczo PEP-8 chce, abyś unikał takich rzeczy
f = lambda x: 2 * x
i zamiast tego użyj
def f(x):
return 2 * x
Jednak, jak opisano w ostatnim raporcie o błędach (sierpień 2014 r.), Następujące oświadczenia są teraz zgodne:
a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x
Ponieważ mój moduł sprawdzania PEP-8 jeszcze tego nie implementuje, na razie wyłączyłem E731.
def
moduł sprawdzania PEP8 narzeka E301 expected 1 blank line, found 0
, więc musisz dodać brzydką pustą linię przed nim.
Zetknąłem się również z sytuacją, w której korzystanie z funkcji def (ined) było niemożliwe.
class SomeClass(object):
# pep-8 does not allow this
f = lambda x: x + 1 # NOQA
def not_reachable(self, x):
return x + 1
@staticmethod
def also_not_reachable(x):
return x + 1
@classmethod
def also_not_reachable(cls, x):
return x + 1
some_mapping = {
'object1': {'name': "Object 1", 'func': f},
'object2': {'name': "Object 2", 'func': some_other_func},
}
W tym przypadku naprawdę chciałem stworzyć mapowanie należące do klasy. Niektóre obiekty w mapowaniu wymagały tej samej funkcji. Nielogiczne byłoby umieszczanie nazwanej funkcji poza klasą. Nie znalazłem sposobu na odwołanie się do metody (metoda statyczna, metoda klasowa lub normalna) z wnętrza klasy. SomeClass jeszcze nie istnieje po uruchomieniu kodu. Odwołanie się do tego z klasy też nie jest możliwe.
also_not_reachable
w definicji mapowania jakoSomeClass.also_not_reachable
f
dla mnie tak dostępna, jak w wersjach 2.7 i 3.5
@staticmethod
i @classmethod
nie potrzebują obiektu, tylko SomeClass.also_not_reachable
(chociaż potrzebują charakterystycznych nazw). Jeśli chcesz uzyskać do nich dostęp metodami klasowymi, po prostu użyjself.also_not_reachable
*not_reachable
metod na not_as_easily_reachable_from_class_definition_as_a_lambda
xD
flake8
( flake8.pycqa.org )