每当我使用 lambda 表达式时,我都会收到此 pep8 警告。不推荐使用 lambda 表达式吗?如果不是为什么?
5 回答
您遇到的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
语句会导致更多的代码行。我对此的主要反应是:是的,这很好。除非你是打代码打高尔夫球,否则你不应该做的事情是尽量减少行数:明确而不是简短。
这是故事,我有一个简单的 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 也没有增加。此时代码检查器会抱怨该函数没有文档字符串。
在我看来,这条规则最好在有意义的时候避免和打破,使用你的判断。
我还遇到了一个甚至无法使用 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 尚不存在。所以从课堂上引用它也是不可能的。
这适用于我在一个类中,删除 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)