使用 or
是否是 Pythonic ,类似于 PHP 如何使用 or die()
?
我一直在使用quiet or print(stuff)
代替if verbose:
print(stuff)
最近。
我认为它看起来更好,他们做同样的事情,而且节省了一条线。在性能方面,一个会比另一个更好吗?
两者的字节码在我看来几乎相同,但我真的不知道我在看什么......or
2 0 LOAD_FAST 0 (quiet)
3 JUMP_IF_TRUE_OR_POP 15
6 LOAD_GLOBAL 0 (print)
9 LOAD_CONST 1 ('foo')
12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
>> 15 POP_TOP
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
对比
if
2 0 LOAD_FAST 0 (verbose)
3 POP_JUMP_IF_FALSE 19
3 6 LOAD_GLOBAL 0 (print)
9 LOAD_CONST 1 ('bar')
12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
15 POP_TOP
16 JUMP_FORWARD 0 (to 19)
>> 19 LOAD_CONST 0 (None)
22 RETURN_VALUE
最佳答案
不,这绝对不是 Pythonic。在此过程中做出的许多决定都是专门为了阻止这种编码。
正确的写法是显而易见的:
if verbose:
print(stuff)
或者,如果计算
stuff
本身并不昂贵/危险/不可撤销,只需包装 print
在检查标志的函数中:def printv(*args, **kwargs):
if verbose:
print(*args, **kwargs)
......所以你可以这样做,这与你将得到的一样简洁:
printv(stuff)
或者,更好的是,使用
logging
模块而不是重新发明轮子。但是如果
stuff
很贵,你真的要省线吗?好吧,您可能真的不需要保存一行,这样做总是为了简洁而牺牲可读性; “可读性计数”是 the Zen of Python 的关键部分.但是 Python 确实允许您将单行套件与条件放在同一行:
if verbose: print(stuff)
如 PEP 8说,“有时可以”,但“通常不鼓励”。正如 Guido 在想法邮件列表上的一封电子邮件中所说的那样,“如果您必须保存一行,请使用单行 if 语句,而不是使用‘聪明’的语句。但如果您必须保存一行,我可能不想阅读你的代码。”
如果你想在一个表达式中使用它(你不应该这样做,我将在下面解释),或者你想在技术上严格遵守 PEP 8,同时公然违反精神:
print(stuff) if verbose else None
那么,有什么不是 Pythonic 的呢?
一方面,您使用的是
print
的结果在表达式中,即使 print
没有任何有用的结果,仅因其副作用而被称为。这是误导。一般来说,Python 每行只有一个副作用,而且它发生在尽可能靠左的地方,这样可以轻松浏览代码并查看发生了什么变化。语句和表达式(以及,例如,赋值是语句)之间的强烈区别,以及具有副作用的方法惯用地返回
None
加强了这一点。而不是 self
, 等等。但即使忽略所有这些,使用
and
和 or
只是为了短路,而不是为了他们的结果,可能会令人困惑,至少在某些人看来,这是丑陋的。这就是为什么添加了三元表达式( spam if eggs else beans
):阻止人们写 eggs and spam or beans
.为什么会令人困惑?一方面,它读起来根本不像英语,除非您阅读的 Perl 代码比实际英语多。另一方面,很容易不小心使用了一个碰巧为假的有效值;当您看到 if
时,您知道不要这样做,并检查是否这样做。 ,但你不在这里。另请注意 print(stuff) if verbose else None
明确表示您正在创造一个值(value),然后您什么都不做;显式总是比隐式好,尤其是当你做一些不常见的事情时。最后,至于性能:(a)谁在乎,以及(b)为什么不测量它而不是通过阅读你不理解的字节码来猜测?
In [511]: quiet = True
In [512]: %timeit quiet or None
10000000 loops, best of 3: 48.2 ns per loop
In [513]: verbose=False
In [514]: %timeit if verbose: pass
10000000 loops, best of 3: 38.5 ns per loop
所以你去了,在快速通过的情况下,
if
语句实际上快了大约 20%,而不是更慢——而且它们都非常快,无论如何都不太可能影响您的程序。如果你在一个紧凑的循环中这样做了 10 亿次并且需要挤出那个性能,你会想要将其余的从循环中提升出来,即使这意味着用两个相同的近似克隆来重复自己代码(特别是考虑到没有 print
的循环更有可能适合缓存等)。如果你想知道为什么,那么,你必须在你关心的特定实现的特定版本上查看这些字节码的实现......但很可能,需要做一个额外的
POP_TOP
而不是将一个合并到前一个操作是差异的一部分。
关于python - 使用 `or` 会不会是 Pythonic,类似于 PHP 使用 `or die()` 的方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26664855/