为什么在 Python 中隐式检查是否为空?
Python 的禅宗说显式优于隐式。
然而,检查集合 c 是否为空的 Pythonic 方法是:
if not c:
# ...
检查集合是否不为空的方法如下:
if c:
# ...
对于任何可能具有“零”或“空”的内容(元组、整数、字符串、无等),
同上这样做的目的是什么?如果我不这样做,我的代码会出现更多错误吗?或者它是否支持更多用例(即:某种多态性),因为人们可以覆盖这些布尔强制?
The Zen of Python says that explicit is better than implicit.
Yet the Pythonic way of checking a collection c for emptiness is:
if not c:
# ...
and checking if a collection is not empty is done like:
if c:
# ...
ditto for anything that can have "zeroness" or "emptiness" (tuples, integers, strings, None, etc)
What is the purpose of this? Will my code be buggier if I don't do this? Or does it enable more use cases (i.e: some kind of polymorphism) since people can override these boolean coercions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这种最佳实践并非没有道理。
在测试
if object:
时,您基本上是在调用对象的__bool__
方法,该方法可以根据对象行为进行重写和实现。例如,集合上的
__bool__
方法(Python 2 中的__nonzero__
)将根据集合是否为空返回一个布尔值。(参考:http://docs.python.org/reference/datamodel.html< /a>)
This best practice is not without reason.
When testing
if object:
you are basically calling the objects__bool__
method, which can be overridden and implemented according to object behavior.For example, the
__bool__
method on collections (__nonzero__
in Python 2) will return a boolean value based on whether the collection is empty or not.(Reference: http://docs.python.org/reference/datamodel.html)
可能被第一条和第三条打败:
Possibly trumped by the first and third items:
“简单总比复杂好。”
“可读性很重要。”
以
if users
为例 - 它比if len(users) == 0
更具可读性"Simple is better than complex."
"Readability counts."
Take for example
if users
-- it is more readable thatif len(users) == 0
是明确的。 “if”明确指出后面的表达式将在布尔上下文中计算。
公平地说,这样
更清晰,编程新手可能会同意。
但对于一个有经验的程序员(至少是这个)来说,后者并不清晰,它是多余的。由于“if”,我已经知道 c 将与 0 进行比较;我不需要被告知两次。
is explicit. The "if" explicitly states that the expression following will be evaluated in boolean context.
It is fair to argue that
is clearer, and a programming novice might agree.
But to an experienced programmer (this one at least) the latter is not clearer, it is redundant. I already know c will be compared with 0 because of the "if"; I don't need to be told twice.
隐式布尔多态性是许多语言的一部分。事实上,这个习语
可以说来自 c!
未分配的指针应包含 NULL,它可以方便地计算为 false,从而使我们能够避免分段错误。
这是一个非常基本的概念,以至于Python很难拒绝它。事实上,考虑到 c 中可用的布尔多态性相当笨拙的版本,很明显(至少对我来说)Python 通过允许任何类型具有可定制的,使得这种行为更加明确。 - 通过 __nonzero__ 定义布尔转换。
Implicit boolean polymorphism is a part of many languages. In fact, the idiom
arguably comes from c!
An unallocated pointer should contain
NULL
, which conveniently evaluates to false, allowing us to avoid a segmentation fault.This is such a fundamental concept that it would hamper python to reject it. In fact, given the fairly clumsy version of boolean polymorphism available in c, it's immediately clear (to me at least) that python has made this behavior much more explicit by allowing any type to have a customizable, well-defined boolean conversion via
__nonzero__
.如果您愿意,可以输入
if len(lst) > 0
,但这有什么意义呢? Python 确实使用一些约定,其中之一是空容器被认为是错误的。您可以使用
object.__nonzero__(self)
:
If you prefer you can type
if len(lst) > 0
, but what would be the point? Python does use some conventions, one of which is that empty containers are considered falseish.You can customize this with
object.__nonzero__(self)
:其他人已经指出,这是传统的逻辑延伸(至少早在 C 语言中,也许更早),即布尔上下文中零为假,非零为真。其他人也已经注意到,在 Python 中,您可以通过自定义魔术方法等实现一些特殊效果。 (这确实直接回答了您的问题“它是否支持更多用例?”)其他人已经注意到,经验丰富的 Python 程序员将学习此约定并习惯该约定,因此这对他们来说是非常明显和明确的。
但老实说,如果您不喜欢这个惯例,并且您只是为了自己的乐趣和利益而编程,那么不要遵循它。明确、清晰、冗余比混淆要好得多,而且事实上,犯冗余总是比混淆要好。
也就是说,归根结底,这并不是一个很难学习的约定,如果您作为小组项目的一部分进行编码,那么最好遵守项目的约定,即使您不同意它们。
Others have already noted that this is a logical extension of the tradition (at least as early as C, perhaps earlier) that zero is false in a Boolean context, and nonzero is true. Others have also already noted that in Python you can achieve some special effects with customized magic methods and such. (And this does directly answer your question "does it enable more use cases?") Others have already noted that experienced Python programmers will have learned this convention and be used to the convention, so it is perfectly obvious and explicit to them.
But honestly, if you don't like that convention, and you are just programming for your own enjoyment and benefit, simply don't follow it. It is much, much better to be explicit, clear, and redundant than it is to be obfuscated, and it's virtually always better to err on the side of redundancy than obfuscation.
That said, when it comes down to it, it's not a difficult convention to learn, and if you are coding as part of a group project, it is best to stick with the project's conventions, even if you disagree with them.
空列表的计算结果为 False 和非空列表的计算结果为 True 是 Python 的核心约定,它足够明确。如果 if 语句的上下文甚至传达了
c
是一个列表的事实,那么len(c) == 0
也不会更明确。我认为
len(c) == 0
只有当你真的想检查长度而不是魔术零或空时才更明确,因为他们的评估可能与长度检查不同。Empty lists evaluating to False and non-empty lists evaluating to True is such a central Python convention that it is explicit enough. If the context of the if-statement even communicates the fact that
c
is a list,len(c) == 0
wouldn't be much more explicit.I think
len(c) == 0
only is more explicit if you really want to check the length and not for magic zeroness or emptiness because their evaluation may differ from the length check.