Я отримую це попередження pep8, коли я використовую лямбда-вирази. Чи не рекомендуються лямбда-вирази? Якщо ні, чому?
Я отримую це попередження pep8, коли я використовую лямбда-вирази. Чи не рекомендуються лямбда-вирази? Якщо ні, чому?
Відповіді:
Рекомендація в PEP-8, яку ви працюєте, це:
Завжди використовуйте оператор def замість оператора присвоєння, який прив'язує лямбда-вираз безпосередньо до імені.
Так:
def f(x): return 2*x
Немає:
f = lambda x: 2*x
Перша форма означає, що ім'я результуючого функціонального об'єкта конкретно 'f' замість загального '<lambda>'. Це корисніше для зворотних зворотів та подання рядків загалом. Використання оператора присвоєння виключає єдину вигоду, яку може запропонувати лямбда-вираз над явним оператором def (тобто, що він може бути вбудований у більший вираз)
Присвоєння лямбдам імен в основному просто дублює функціональність def
- і взагалі, найкраще зробити щось єдиним способом, щоб уникнути плутанини та підвищення чіткості.
Законний випадок використання лямбда - це те, де ви хочете використовувати функцію, не призначаючи її, наприклад:
sorted(players, key=lambda player: player.rank)
Загалом, головний аргумент проти цього полягає в тому, що у def
твердженнях з'явиться більше рядків коду. Моя основна відповідь на це була б: так, і це нормально. Якщо ви не кодуєте гольф, мінімізація кількості ліній - це не те, що вам слід робити: займіться ясним за короткий час.
def
через перевірку PEP8, ви отримуєте E704 multiple statements on one line (def)
, і якщо розділити його на два рядки, ви отримаєте E301 expected 1 blank line, found 0
: - /
Ось історія, у мене була проста лямбда-функція, яку я використовував двічі.
a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)
Це лише для представлення, я зіткнувся з парою різних версій цього.
Тепер, щоб утримати речі, я починаю повторно використовувати цю звичайну лямбда.
f = lambda x : x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
На даний момент моя перевірка якості коду скаржиться на те, що лямбда називається функцією, тому я перетворюю її у функцію.
def f(x):
return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
Тепер перевірявач скаржиться, що функція повинна бути обмежена одним порожнім рядком до і після.
def f(x):
return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
Тут ми маємо 6 рядків коду замість оригінальних 2 рядків, не збільшуючи читабельності та не збільшуючись, будучи пітонічними. У цей момент програма перевірки коду скаржиться на те, що функція не має документації.
На мою думку, цього правила краще уникати та порушувати, коли це має сенс, використовувати своє судження.
a = [x + offset for x in simple_list]
. Не потрібно використовувати map
і lambda
тут.
x + offset
частину до абстрагованого місця, яке можна оновити, не змінюючи більше одного рядка коду. Як ви вже згадали список розуміння списку, вам все одно знадобляться два рядки коду, які x + offset
міститимуть їх, вони зараз будуть в списку розумінь. Для того, щоб витягнути їх так, як хотів автор, вам знадобиться def
або lambda
.
def
та, lambda
можна також використовувати functools.partial : f = partial(operator.add, offset)
а потім a = list(map(f, simple_list))
.
def f(x): return x + offset
(тобто простої функції, визначеної в одному рядку)? Принаймні, з flake8 я не отримую скарг на порожні рядки.
a, b = [[x + offset for x lst] for lst in (simple_list, another_simple_list)]
Lattyware абсолютно прав: PEP-8 прагне, щоб ви уникали подібних речей
f = lambda x: 2 * x
і замість цього використовувати
def f(x):
return 2 * x
Однак, як було зазначено в недавньому звіті про помилки (серпень 2014 р.), Такі твердження, як наведено нижче, тепер сумісні:
a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x
Оскільки моя перевірка PEP-8 ще не реалізує це правильно, я поки що вимкнув E731.
def
, шашка PEP8 скаржиться на E301 expected 1 blank line, found 0
, тому вам доведеться перед цим додати некрасиву порожню лінію.
Я також зіткнувся з ситуацією, в якій навіть неможливо було використовувати функцію def (ined).
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},
}
У цьому випадку мені дуже хотілося зробити відображення, яке належало до класу. Деякі об’єкти в картографуванні потребували тієї ж функції. Було б нелогічно ставити названу функцію поза класом. Я не знайшов способу звернутися до методу (staticmethod, classmethod або normal) зсередини тіла класу. SomeClass ще не існує при запуску коду. Тому посилання на нього з класу також неможливо.
also_not_reachable
у визначенні відображення якSomeClass.also_not_reachable
f
як і для мене 2,7 та 3,5
@staticmethod
і @classmethod
не потребують об'єкт, просто SomeClass.also_not_reachable
(хоча їм потрібні відмінні назви). Якщо вам потрібно отримати доступ до них з методів класу, просто використовуйтеself.also_not_reachable
*not_reachable
методи як not_as_easily_reachable_from_class_definition_as_a_lambda
xD
flake8
( flake8.pycqa.org )