奇怪的行为:函数的三元运算符

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 是的,这很好,虽然它的运行速度可能比原始版本慢一些。 我不确定我明白为什么它会变慢。它避免了每次调用f1f2 时创建函数的开销,因此如果有的话,它会(微不足道地)提高性能。我不会说任何一种方式的差异都值得担心。 @Asad 我的评论是基于这样的假设,即原始方法每次调用仅做出一次决定,然后使用lambdas 之一作为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])

解决方法是将单个 lambdas 括在括号中:

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 的子类)。

【讨论】:

以上是关于奇怪的行为:函数的三元运算符的主要内容,如果未能解决你的问题,请参考以下文章

C ++中的三元运算符奇怪的行为

javascript:使用三元运算符的意外评估行为

C 三元运算符的意外结果

不同行为的三元运算符 - if/else 与扩展运算符 (...)

?:将一个表达式留空时的三元条件运算符行为

具有不同类型表达式的三元运算符[重复]