E731 не назначайте лямбда-выражение, используйте def
Я получаю это предупреждение pep8 всякий раз, когда я использую лямбда-выражения. Не рекомендуется ли использовать лямбда-выражения? Если нет то почему?
5 ответов:
рекомендация PEP-8 вы бежите в это:
всегда используйте оператор def вместо оператора присваивания, который связывает лямбда-выражение непосредственно с именем.
да:
def f(x): return 2*x
нет:
f = lambda x: 2*x
первая форма означает, что имя в результате объект функции-это конкретно 'f' вместо общего '
'. Это более полезно для трассировки и строки представления в генеральный. Использование оператора присваивания исключает подошву преимущество лямбда-выражение может предложить над явным оператором def (т. е. что он может быть встроен в большее выражение) назначение лямбд именам в основном просто дублирует функциональность
def
- и вообще, лучше всего делать что-то одним способом, чтобы избежать путаницы и повысить ясность.законный случай использования для лямбда-это то, где вы хотите чтобы использовать функцию без ее назначения, например:
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 линии, без увеличения читаемости и увеличения время обновления. На этом этапе средство проверки кода жалуется на то, что функция не имеет docstrings.
на мой взгляд, этого правила лучше избегать и нарушать, когда это имеет смысл, используйте свое суждение.
Lattyware абсолютно прав: в принципе PEP-8 хочет, чтобы вы избегали таких вещей, как
f = lambda x: 2 * x
и вместо того, чтобы использовать
def f(x): return 2 * x
однако, как указано в недавнем bugreport (Aug 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 еще не существует, когда выполняется код. Так обращение к нему из класса также невозможно.
лямбды можно использовать для ленивых оценок, таким образом откладывая некоторые дорогостоящие операции до тех пор, пока их результаты не понадобятся на самом деле.
Я только что столкнулся с одним случаем (по проблеме конкуренции/практики кода), где я вычислял относительно дорогие функции pow () (относительно дорогие, поскольку вход состоял из полумиллиона тестовых случаев) для 3 разных случаев и определенных комбинаций из 3 случаев. Для ясности кода я бы вычислил все 3 случая, а затем вернул комбинацию из 3, которые были действительно необходимы для текущего запроса.
к сожалению, это генерировало TLE ("превышен лимит времени") на некоторых входах.
используя лямбды для отсрочки дорогостоящих операций pow (), я смог решить проблемы TLE, поскольку на самом деле были вызваны только вычисления, относящиеся к текущему запросу.
поэтому я думаю, что это тот случай, когда предупреждение E731 на самом деле не применимо и должно быть отключено..