E731 не назначают лямбда-выражение, используйте def

Я получаю это предупреждение pep8 всякий раз, когда я использую лямбда-выражения. Не рекомендуется ли лямбда-выражения? Если не так?

Ответ 1

Рекомендация в PEP-8, в которой вы работаете:

Всегда используйте инструкцию def вместо инструкции присваивания, которая связывает лямбда-выражение непосредственно с именем.

Да:

def f(x): return 2*x 
<Не p > Нет:
f = lambda x: 2*x 

Первая форма означает, что имя получающейся функциональный объект - это скорее "f", а не общий ". Это более полезно для отслеживания и строковых представлений в Генеральная. Использование оператора присваивания исключает единственную выгода выражения lambda может предложить более явное определение def (т.е. что он может быть встроен в большее выражение)

Назначение lambdas для имен в основном просто дублирует функциональность def - и в целом лучше всего сделать что-то одним способом, чтобы избежать путаницы и повысить ясность.

Допустимым вариантом использования лямбда является то, где вы хотите использовать функцию без ее назначения, например:

sorted(players, key=lambda player: player.rank)

Ответ 2

Вот история, у меня была простая лямбда-функция, которую я использовал дважды.

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)

В этот момент мой контролер качества кода жалуется, что lambda является именованной функцией, поэтому я конвертирую ее в функцию.

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 строк без увеличения читаемости и без увеличения pythonic. На этом этапе программа проверки кода жалуется на функцию, не имеющую докстрон.

По-моему, это правило лучше избегать и нарушать, когда это имеет смысл, используйте свое мнение.

Ответ 3

Lattyware абсолютно прав: в основном PEP-8 хочет, чтобы вы избегали таких вещей, как

f = lambda x: 2 * x

и вместо этого используйте

def f(x):
    return 2 * x

Однако, как описано в недавнем bugreport (август 2014 г.), теперь выполняются следующие утверждения:

a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x

Так как моя контрольная панель PEP-8 не реализует это правильно, я пока не выключил E731.

Ответ 4

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

Ответ 5

Lambdas может использоваться для ленивых оценок, таким образом откладывая некоторые дорогостоящие операции, пока их результаты не понадобятся.

Я просто столкнулся с одним случаем (по проблеме конкуренции/практики с кодом), где я вычислял относительно дорогие функции pow() (относительно дорого, так как вход состоял из полумиллиона тестовых случаев) для 3 разных случаев и некоторых комбинаций из 3 случаев. Для ясности кода я бы вычислил все 3 случая, а затем вернул комбинацию из 3, которые были действительно необходимы для текущего запроса.

К сожалению, это привело к созданию TLE ( "превышение времени" ) на определенных входах.

Используя lambdas для отсрочки дорогостоящих операций pow(), я смог разрешить проблемы TLE, поскольку на самом деле были вызваны только вычисления, имеющие отношение к текущему запросу.

Итак, я думаю, что это случай, когда предупреждение E731 действительно не применимо и должно быть отключено..