使用哪个三元运算符?

loa*_*in_ 1 python syntax python-2.x python-2.7

我一直想知道我是否应该写作

lambda pixel: (0,0,0) if pixel == (0,0,0) else (255,255,255),
Run Code Online (Sandbox Code Playgroud)

要么

lambda pixel: pixel if pixel == (0,0,0) else (255,255,255),
Run Code Online (Sandbox Code Playgroud)

这可能是一个愚蠢的问题,但我想更好地形成问题.

我想知道是否有任何我不知道的警告.

我个人认为后者更具可读性.

ste*_*eha 7

绝对是后者.

如果您使用前者,并且某人只编辑其中一个文字值,那么现在它已被破坏:

lambda pixel: (0,0,0) if pixel == (0,0,8) else (255,255,255),
Run Code Online (Sandbox Code Playgroud)

我在上面介绍了一个bug.我编辑了条件中使用的元组,但没有编辑第一个元组.通过临时检查很难发现这一点.

考虑一下:

big_long_expression if something == big_long_expression else whatever
Run Code Online (Sandbox Code Playgroud)

读者必须big_long_expression每次都进行心理评估,并比较它们是否实际相同.如果您改为使用后一种形式,现在很清楚:您要么保持表达式不变,要么在其他情况下返回其他内容.

这与我更喜欢+=运营商的原因相同:

my_class.a.b[i+3] = my_class.a.b[i+3] + 2
Run Code Online (Sandbox Code Playgroud)

与之比较:

my_class.a.b[i+3] += 2
Run Code Online (Sandbox Code Playgroud)

两者都做同样的事情,但第二个更容易理解.

我总是更喜欢更清楚地表达你的意图的语法.我认为你的第二种格式最清楚:检查一个条件,当它是真的时单独保留值,否则返回一个特殊值.

编辑:直接在这个问题的评论中,@ DSM提出了一个很好的观点.第一个表达式也有一个微妙的属性:它总是返回一个元组,即使被比较的表达式不是一个元组.只要pixel任何可以与元组进行比较的类,任何一个表达式都可以.但是如果你想让你的lambda始终从三元组的任何一个元素中返回一个元组,那么第一个形式是可取的.

以下是对代码的两次重写,供您考虑.

首先:

ORIGIN = (0, 0, 0)
lambda pixel: ORIGIN if pixel == ORIGIN else (255,255,255),
Run Code Online (Sandbox Code Playgroud)

现在至少有一个点可以编辑来改变原点.如果你想要总是返回一个元组,这就是我推荐的方式.

第二:

lambda pixel: pixel if pixel == (0, 0, 0) else type(pixel)((255, 255, 255))
Run Code Online (Sandbox Code Playgroud)

获取类型pixel,然后调用该类型来构造新对象.这假设pixel类不仅可以与元组进行比较,而且如果将元组传递给类,它将使用它来构建基于元组的类的新实例.

使用中的一个例子:

f = lambda pixel: pixel if pixel == (0, 0, 0) else type(pixel)((255, 255, 255))

class T(tuple):
    """
    Make a class that acts exactly like a tuple.
    """
    pass

x = T((1,2,3))
assert type(x) == T
assert type(x) == type(f(x))

x = (1, 2, 3)
assert type(x) == tuple
assert type(x) == type(f(x))
Run Code Online (Sandbox Code Playgroud)