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

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

5 ответов


рекомендация PEP-8 вы сталкиваетесь с:

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

да:

def f(x): return 2*x 

нет:

f = lambda x: 2*x 

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

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

законный случай использования для лямбда-это то, где вы хотите чтобы использовать функцию без ее назначения, e.g:

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

для простых операций, the operator модуль предоставляет некоторые полезные опции в attrgetter, itemgetter и methodcaller который часто может заменить labmdas, которые просто обращаются к атрибутам, элементам и вызывающим методам.

например, вышеуказанное можно сделать с помощью operator.attrgetter вот так:

sorted(players, key=operator.attrgetter('rank'))

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

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

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


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 checker еще не реализует это правильно, я отключил E731 на данный момент.


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


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

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

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

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

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