哪个更好?
if not var:
var = get_var()
(或者)var = var 或 get_var()
另外,我怎么知道两者中的哪一个?
编辑:
史蒂夫的另一种选择,
var = var if var else get_var()
哪个更好?
if not var:
var = get_var()
(或者)var = var 或 get_var()
另外,我怎么知道两者中的哪一个?
编辑:
史蒂夫的另一种选择,
var = var if var else get_var()
更好的是你更喜欢的那个。我会使用第一个版本,if
但这是非常个人化的。
当两种风格的变体在风格上如此接近时,我将timeit
其用作决胜局:更快必须意味着更接近 Python 的主流,即更好。嘿,这比无休止的辩论要好,是吗?-) 所以:
$ python -mtimeit -s'var=0; getvar=lambda:0' 'var = var or getvar()'
1000000 loops, best of 3: 0.359 usec per loop
$ python -mtimeit -s'var=0; getvar=lambda:0' 'if not var: var = getvar()'
1000000 loops, best of 3: 0.361 usec per loop
$ python -mtimeit -s'var=1; getvar=lambda:1' 'var = var or getvar()'
10000000 loops, best of 3: 0.123 usec per loop
$ python -mtimeit -s'var=1; getvar=lambda:1' 'if not var: var = getvar()'
10000000 loops, best of 3: 0.0899 usec per loop
有它——当它是假的时候if
等价,当它是.var
true
实际上,如果您试图确定 var 之前是否已通过调用 get_var 设置,那么我认为这两种形式都是错误的。Python 将许多完全普通的值视为布尔值“false”:0、None、[]、(,)、set() 和 {}。因此,假设 var 将是一个整数,而 get_var() 恰好返回 0。现在,无论您使用哪种形式,get_var() 都会一次又一次地被调用,即使我们已经知道 var 是 0!
有几种方法可以检测变量是否已定义:
查看 globals() 或 locals() 返回的字典
将语句包装var = var
在 try/except 块中,捕获 NameError
使用类似 None 的标记值,并将 var 初始化为该值;然后你可以测试if var is None: var = get_var()
(使用'is',而不是'==')。如果你运气不好,并且 None 是从 get_var() 返回的潜在值,那么你需要定义你自己的特殊尚未定义的值,使用类似的东西NOT_DEFINED = object()
,用它初始化 var,然后你可以测试为if var is NOT_DEFINED
.
对我来说,第一个习语,即使用显式 if 的习语更可取,因为更显式。
但是,我已经看到 or 构造被引用为首选/更 Pythonic 的构造。
所以,一方面,Explicit is better than implicit
(Zen citation),另一方面,short 表达式可以被视为 pythonic(尽管在所有情况下,short 并不等同于 pythonic!)
一个密切相关的 SO 问题是将 None 转换为空字符串的最惯用方式,并且 if 和 the or 成语都列在那里。
第一个版本对我来说更直观。但话又说回来,这完全取决于你自己的口味。
第二个更pythonic,我通常使用它。
两者都没有错。
对于阅读代码的人来说,前者更容易理解。
问问自己,当您考虑要解决的问题时,想到的概念是否更接近“如果这个,那么那个”或“两个几乎但不完全是布尔变量的逻辑或”。
考虑到 or 是一个短路运算符,两者最终都会编译成相同的代码(如果左手为真,它不会评估右手参数)。
我更喜欢第一个,因为它更清楚地表达了您的意图。第二个可能更紧凑。
解释器可能会同时执行它们。在代码可读性方面存在权衡。哪个语句更容易识别它的作用?当然,第一个要清楚得多。对我来说,阅读这篇文章,我不得不更多地考虑第二个。由于可读性增加,我会使用第一个,即使第二个语句稍微“性感”。
希望这可以帮助。
-tjw