奇怪的行为:函数的三元运算符
Posted
技术标签:
【中文标题】奇怪的行为:函数的三元运算符【英文标题】:Strange behavior: ternary operator for functions 【发布时间】:2015-04-07 08:46:55 【问题描述】:这是我的问题的简化示例。我认为这些函数会有完全相同的行为:
def f1(l):
if type(l[0][0])==list: f=lambda x:x[0][0]
else: f=lambda x:x[0]
l.sort(key=f,reverse=True)
def f2(l):
f=lambda x:x[0][0] if type(l[0][0])==list else lambda x:x[0]
l.sort(key=f,reverse=True)
l=[[1,2],[3,4]]
但实际上f1(l)
在f2(l)
崩溃但异常时工作正常:
IndexError: list index out of range
所以问题是为什么会这样,是否可以使用三元运算符来返回其中一个函数?
【问题讨论】:
这有点切题,但也许这是 lambda 使事情变得不那么容易阅读而不是更容易阅读的情况之一。一个检查x
并返回x[0]
或x[0][0]
或您需要的任何东西的def getKey(x):
怎么样?然后l.sort(key=getKey,reverse=True)
.
@Asad 是的,这很好,虽然它的运行速度可能比原始版本慢一些。
我不确定我明白为什么它会变慢。它避免了每次调用f1
或f2
时创建函数的开销,因此如果有的话,它会(微不足道地)提高性能。我不会说任何一种方式的差异都值得担心。
@Asad 我的评论是基于这样的假设,即原始方法每次调用仅做出一次决定,然后使用lambda
s 之一作为key
,而getkey
方法检查列表中的每个元素并且每次都做出相同的(冗余)决定。我做了一些测试。他们表明,原始方法比getkey
快大约 2 倍。不过,这对我的任务并不重要。在这种情况下,我投票支持可读性。
啊,是的,你是对的。在这种情况下,您可以从 getKey
返回正确的 lambda,并拥有 l.sort(key=getKey(l),reverse=True)
。
【参考方案1】:
lambda
具有lowest precedence among operators。这就是为什么 Python 将该行解析为
f = lambda x: (x[0][0] if type(l[0][0]) == list else lambda x: x[0])
解决方法是将单个 lambda
s 括在括号中:
f = (lambda x: x[0][0]) if type(l[0][0]) == list else (lambda x: x[0])
也就是说,type(l[0][0]) == list
有点错误,isinstance(l[0][0], list)
将是最好的方法(它还处理list
的子类)。
【讨论】:
以上是关于奇怪的行为:函数的三元运算符的主要内容,如果未能解决你的问题,请参考以下文章