Я получаю это предупреждение 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},
}
В этом случае я действительно хотел сделать отображение, которое принадлежало классу. Некоторые объекты в отображении нуждались в той же функции. Было бы нелогично помещать именованную функцию вне класса. Я не нашел способ ссылаться на метод (статический метод, метод класса или обычный) изнутри тела класса. 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 )