Python:避免使用if条件?
哪个更好呢?
if not var:
var = get_var()
(或者)
var = var or get_var()
另外,我怎么知道这两者哪个更好呢?
补充:
还有一个来自steve的选项,
var = var if var else get_var()
9 个回答
其实,如果你想判断变量 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
。
当两种样式的变化非常相似时,我会用 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
为假时,它们是等价的,而当 var
为真时,它更快。
哪个更好,主要看你自己喜欢哪个。我个人会选择第一个版本,用if
语句,但这完全是个人的偏好。