为什么Python中没有明确的空位检查(例如``Empty`)

时间:2010-08-15 17:37:54

标签: python

The Zen of Python说“明确胜过隐性”。然而,用于检查空虚的“pythonic”方法是使用隐含的booleaness:

if not some_sequence:
    some_sequence.fill_sequence()

如果some_sequence是空序列,但如果它是None0,则会出现这种情况。

与理论明确空虚检查比较:

if some_sequence is Empty:
    some_sequence.fill_sequence()

对于一些不利的选择变量名称,检查空虚的隐含booleaness会变得更加混乱:

if saved:
    mess_up()

与:比较:

if saved is not Empty:
    mess_up()

另见:“Python: What is the best way to check if a list is empty?”。我觉得具有讽刺意味的是,投票最多的答案声称隐含的是pythonic。

为什么没有明确的空白检查有更高的理由,例如Python中的is Empty

5 个答案:

答案 0 :(得分:22)

if foo:if not foo:中的多态性不违反“隐式vs显式”:它显式委托给被检查对象的任务,知道它是否属实或者是假的。这意味着什么(以及如何最好地检查它)显然确实并且必须依赖于对象的类型,因此样式指南要求委托 - 让应用程序级代码傲慢地断言它比对象更好地知道愚蠢的高度。

此外,X is Whatever总是,总是意味着X 与Whatever完全相同的对象。为EmptyWhatever的任何其他特定值制作一个完全唯一的例外将是荒谬的 - 很难想象一个更加非语言的方法。并且“完全相同的对象”显然是可传递的 - 所以你再也不能拥有不同的空列表,空集,空的序列......祝贺你,你刚刚设计了一个完全无法使用和无用的语言,每个空容器疯狂地“折叠”到一个空的容器对象(想象一下当有人试图改变一个空容器时的乐趣......?!)。

答案 1 :(得分:14)

一旦您了解了is Empty运算符的作用,没有is的原因非常简单。

来自python manual

  

运算符isis not测试对象标识:x is y为真   当且仅当xy是同一个对象时。 x is not y产生了   反向真值。

这意味着some_sequence is Empty会检查some_sequence是否与Empty是同一个对象。这不符合你的建议。

考虑以下示例:

>>> a = []
>>> b = {}

现在让我们假装在python中有这个is Empty构造:

>>> a is Empty
True
>>> b is Empty
True

但是,由于is运算符执行身份检查,这意味着abEmpty相同。反过来,这必须意味着ab是相同的,但它们不是:

>>> a is b
False

所以回答你的问题“为什么python中没有is Empty?”:因为is进行身份检查。

为了拥有is Empty构造,你必须破解is运算符以表示其他东西或者创建一些神奇的Empty对象,它以某种方式检测空集合然后与它们相同

您应该问为什么没有调用特殊方法is Empty的内置函数isempty(),而不是问为什么没有__isempty__()

所以不要使用隐含的booleaness:

if saved:
  mess_up()

我们有明确的空检查:

if not isempty(saved):
  mess_up()

saved的类具有__isempty__()方法,以实现某些理智的逻辑。

我发现这比使用隐含的booleaness进行清空检查要好得多。

当然,您可以轻松定义自己的isempty()功能:

def isempty(collection):
  try:
    return collection.__isempty__()
  except AttributeError:
    # fall back to implicit booleaness but check for common pitfalls
    if collection is None:
      raise TypeError('None cannot be empty')
    if collection is False:
      raise TypeError('False cannot be empty')
    if collection == 0:
      raise TypeError('0 cannot be empty')
    return bool(collection)

然后定义一个__isempty__()方法,该方法为所有集合类返回一个布尔值。

答案 2 :(得分:5)

我同意有时if foo:对我来说并不明确,因为我真的想告诉读者这段代码我正在测试它的空虚。在这些情况下,我使用if len(foo):。足够明确。

我100%同意Alex w.r.t is Empty是unpythonic。

答案 3 :(得分:0)

考虑到Lisp一直使用()空列表或其符号NIL几年作为False和T或任何非NIL作为True,但通常计算Truth已经产生了一些有用的结果,如果需要则不需要重现。看看字符串的分区方法,其中中间结果非常好用,而非空控件是True约定。

我一般都试着避免使用len,因为它在紧密循环中非常昂贵。在程序逻辑中更新结果的长度值而不是重新计算长度通常是值得的。

对我来说,我更喜欢Python将False设为()或[]而不是0,但就是这样。那么使用not []作为非空是更自然的。但是now()不是[]是True所以你可以使用:

emptyset = set([])    
if myset == emptyset:

如果你想明确空集的情况(不是我的设置([]))

我自己非常喜欢 if my myset 作为我的评论者。

现在我想到这可能是最接近显式的not_empty:

if any(x in myset for x in myset): print "set is not empty"

所以空是:

if not any(x in myset for x in myset): print "set is empty"

答案 4 :(得分:0)

是Python中可迭代的显式空白检查。拼写为not。隐含在那里的是什么?当iterable为空时not给出True,当非空时给出False。

你究竟反对什么?一个名字?正如其他人告诉你的那样,它肯定比is Empty好。并不是那么不合理:考虑到Python中通常命名的东西,我们可能想象一个名为widgets的序列,令人惊讶地包含一些小部件。然后,

if not widgets:

可以理解为“如果没有小部件......”。

或者你反对这个长度?明确并不意味着冗长,这是两个不同的概念。 Python没有addition方法,它有+运算符,如果您知道要应用它的类型,则它是完全明确的。与not相同的事情。