我已经这样做了一段时间:
x = x if x else y
None
在 x 可能是、False
、0
、''
、[]
或的各种上下文中{}
。
我知道纯粹主义者宁愿我:
if not x:
x = y
但忘了这一点,这不是我的问题。我的问题是:
x = x if x else y
除了它是三元组之外,还有什么“错误”吗?具体来说,是否可以进行这样的三元自分配。
笔记
我的问题不行x = x if C else y
。我知道它是。
非常感谢
不,这没什么错。
事实上,它非常pythonic。我记得读过那是(Guido 本人)首选的三元等效项。我会看看我是否可以挖掘参考。
就个人而言,我发现另一种方式更具可读性,但你没有征求我的个人意见。;)
更新:这是引文。核心 Python 编程,第 2 版;韦斯利·洪;普伦蒂斯大厅 2007
如果您来自 C/C++ 或 Java 世界,那么很难忽略或克服 Python 很长时间没有条件或三元运算符 (C ? X : Y) 的事实。[...] Guido 拒绝在 Python 中添加这样的功能,因为他相信保持代码简单并且不会给程序员提供简单的方法来混淆他们的代码。然而,十多年后,他放弃了,主要是因为人们尝试使用和和或多次错误地模拟它的容易出错的方式。根据常见问题解答,正确的一种方法是 (C and [X] or [Y])[0]。唯一的问题是社区无法就语法达成一致。(你真的必须看看 PEP 308 才能看到所有不同的提议。) 这是人们表达强烈感情的 Python 领域之一。最终决定归结为 Guido 在所有选择中选择最喜欢(也是他最喜欢的),然后将其应用于标准库中的各种模块。根据 PEP 的说法,“这篇评论近似于现实世界用例的样本,涵盖了各种应用程序,由许多具有不同背景的程序员编写。” 这是最终选择集成到 Python 2.5 中的语法:X if C else Y。
从语言设计的角度来看,没有错。正如另一位海报所提到的,这甚至是首选方式。我什至会问你为什么暗示作为三元是错误的?
从可读性/可维护性的角度来看,事情更具可数据性。一方面,如果您将有很多随意的、非 Python 的阅读器/维护者,那么这个结构(相对于if not x: x= C
)的可读性可能会低得多。另一方面,您的程序很可能包含许多其他(和更深层次的)Pythonism。您有权从您的“读者”那里获得最低限度的知识。
从性能的角度来看,x
作为变量,两种形式都可以通过不同的实现优化(如果没有有效优化)到相同的代码中。这意味着这些术语没有区别。
更新:
我不知道 Guido 对@Edward 引用的主题的看法。我很高兴他同意我的看法。或者我和他。x= (x,C)[not x]
但是他关于引入三元运算符是绝对正确的,因为它比诸如or 之类的替代方案要清晰得多x= x or C
,许多具有 C 背景的早期 Python 程序员使用(和推广)(也许也作为“酷”,与众不同的东西)。顺便说一句,两者通常都是正确的(取决于预期的确切语义)。
使用三元 for 没有任何问题x = x if c else y
,但是,在x = x if x else y
逻辑确实只是简化为的情况下
x = x or y
这是因为在 Python 中x or y
计算结果为“如果 x 为假,则 y,否则 x”
所以x if x else y
== y if not x else x
==x or y
显然,x or y
是最清楚的,应该使用。
我犹豫要不要这样做,因为这是我的真实观点:
不要微优化。使用你觉得舒服的东西;使用使您的代码最易读的东西。如果您认为这是最易读的,那么三元语句非常好。
也就是说,
ben@nixbox:~$ python3 -m timeit 'x = 1; x=x if x else 2'
10000000 loops, best of 3: 0.0345 usec per loop
ben@nixbox:~$ python3 -m timeit '''
> x=1
> if not x:
> x=2
> '''
10000000 loops, best of 3: 0.0239 usec per loop
将 x 分配回自身会产生一些小的开销。
dis.dis(f)
2 0 LOAD_FAST 0 (x)
3 POP_JUMP_IF_FALSE 12
6 LOAD_FAST 0 (x) #this is the extra instruction
9 JUMP_FORWARD 3 (to 15)
>> 12 LOAD_CONST 1 (1)
>> 15 STORE_FAST 0 (x)
18 LOAD_CONST 0 (None)
21 RETURN_VALUE
回到我的主要观点:别担心。使用你觉得舒服的东西。