E731不分配lambda表达式,使用def

每当我使用lambda表达式时,我都会得到这个pep8警告。不建议使用lambda表达式吗?如果不是,为什么?

106833 次浏览

你在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语句将导致更多的代码行。我对此的主要回答是:是的,这很好。除非你在打代码高尔夫,否则尽量减少行数不是你应该做的事情:追求清晰而不是简短。

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

f = lambda x: 2 * x

而是使用

def f(x):
return 2 * x

然而,正如在最近的bugreport(2014年8月)中所述,以下语句现在是兼容的:

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

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

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

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行,可读性没有增加,python化也没有增加。此时,代码检查器抱怨函数没有文档字符串。

在我看来,最好避免这个规则,当它有意义时,使用你的判断。

我还遇到过一种情况,在这种情况下,甚至不可能使用已定义的函数。

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},
}
在这种情况下,我真的想做一个属于类的映射。映射中的某些对象需要相同的函数。将a命名函数放在类之外是不合逻辑的。 我还没有找到从类主体内部引用方法(staticmethod, classmethod或normal)的方法。当代码运行时,SomeClass还不存在。所以从类中引用它也是不可能的。< / p >

这适用于我在一个类,删除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)