264

每当我使用 lambda 表达式时,我都会收到此 pep8 警告。不推荐使用 lambda 表达式吗?如果不是为什么?

4

5 回答 5

312

您遇到的PEP-8中的建议是:

始终使用 def 语句而不是将 lambda 表达式直接绑定到名称的赋值语句。

是的:

def f(x): return 2*x 

不:

f = lambda x: 2*x 

第一种形式意味着生成的函数对象的名称是专门的“f”而不是通用的“<lambda>”。这对于一般的回溯和字符串表示更有用。赋值语句的使用消除了 lambda 表达式相对于显式 def 语句所能提供的唯一好处(即它可以嵌入到更大的表达式中)

将 lambdas 分配给名称基本上只是复制了def- 而且一般来说,最好以单一方式做某事以避免混淆并增加清晰度。

lambda 的合法用例是您希望在不分配函数的情况下使用函数,例如:

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

一般来说,反对这样做的主要论据是def语句会导致更多的代码行。我对此的主要反应是:是的,这很好。除非你是打代码打高尔夫球,否则你不应该做的事情是尽量减少行数:明确而不是简短。

于 2014-07-29T07:31:26.803 回答
154

这是故事,我有一个简单的 lambda 函数,我使用了两次。

a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)

这只是为了表示,我遇到了几个不同的版本。

现在,为了保持干燥,我开始重用这个常见的 lambda。

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 也没有增加。此时代码检查器会抱怨该函数没有文档字符串。

在我看来,这条规则最好在有意义的时候避免和打破,使用你的判断。

于 2016-05-27T18:14:39.970 回答
28

Lattyware 是绝对正确的:基本上PEP-8希望你避免类似的事情

f = lambda x: 2 * x

而是使用

def f(x):
    return 2 * x

但是,正如最近的错误报告(2014 年 8 月)中所述,以下语句现在是合规的:

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

由于我的 PEP-8 检查器还没有正确实现这一点,我暂时关闭了 E731。

于 2015-01-13T17:32:28.720 回答
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 尚不存在。所以从课堂上引用它也是不可能的。

于 2016-06-16T14:12:36.133 回答
-2

这适用于我在一个类中,删除 lambda 表达式并使用 def 代替,改变这个......

    def set_every(self, every: int = 1, time_unit: int = TimeUnit.Day):
        every_func = lambda x: "*" if x == 1 else "*/" + str(x)
        if TimeUnit.has_value(time_unit):
            self.month_of_year = "*"
            self.day_of_month = "*" if time_unit != TimeUnit.Day else every_func(every)
            self.day_of_week = "*" if time_unit != TimeUnit.Week else every_func(every)

这样...

    def set_every(self, every: int = 1, time_unit: int = TimeUnit.Day):
        def every_func(x: int) -> str: return "*" if x == 1 else "*/" + str(x)
        if TimeUnit.has_value(time_unit):
            self.month_of_year = "*"
            self.day_of_month = "*" if time_unit != TimeUnit.Day else every_func(every)
            self.day_of_week = "*" if time_unit != TimeUnit.Week else every_func(every)
于 2021-08-28T23:13:43.077 回答