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

les*_*ana 22 python

Python的禅宗说"明确比隐含更好".然而,用于检查空虚的"pythonic"方法是使用隐含的booleaness:

if not some_sequence:
    some_sequence.fill_sequence()
Run Code Online (Sandbox Code Playgroud)

如果some_sequence是空序列,那么这将是真的,但如果它是None或,则为真0.

与理论明确的空洞检查比较:

if some_sequence is Empty:
    some_sequence.fill_sequence()
Run Code Online (Sandbox Code Playgroud)

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

if saved:
    mess_up()
Run Code Online (Sandbox Code Playgroud)

与之比较:

if saved is not Empty:
    mess_up()
Run Code Online (Sandbox Code Playgroud)

另请参阅:" Python:检查列表是否为空的最佳方法是什么? ".我觉得具有讽刺意味的是,投票最多的答案声称隐含的是pythonic.

那么为什么没有明确的空洞检查有更高的原因,比如is Empty在Python中?

Ale*_*lli 22

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

而且,X is Whatever总是意味着X 与Whatever 完全相同.制作一个完全独特的例外Empty或任何其他具体价值Whatever将是荒谬的 - 很难想象一个更unpythonic方法.并且"完全相同的对象"显然是可传递的 - 所以你再也不能拥有不同的空列表,空集,空的序列......祝贺你,你刚刚设计了一个完全无法使用且无用的语言,每个空容器都在这里疯狂地"折叠"到一个空的容器对象(想象一下当有人试图改变一个空容器时的乐趣......?!).

  • @Glenn,是的,这是一个非常含蓄的东西 - 足够糟糕地使用"+"来表示"et",正如Nicole d'Oresme(或抄写员)在14世纪所做的那样,但将其扩展为"正面"(正如Johannes Widmann在15日所做的那样,甚至更糟糕的是"加入"(正如Heinrich Schreyber在16日所做的那样),只是无法容忍的隐藏,并且是一种永远不会流行的时尚.看看Cobol的"ADD X to Y GIVING Z"有多好和更明确,而不是"Z = X + Y"的无法忍受的隐含性是这个新贵的Python东西!这些天青年...... (9认同)
  • 但真理和空虚是完全不同的概念!声明委托对象的真实性是有意义的**当且仅当**存在由对象封装的明确布尔值时,这是可以的.对于序列/数组的情况,为什么空到真的等价比任何"真实的所有项都是真的"的等价更好?我同意OP; 如果它们是空的,它们似乎令人困惑和隐含地理解序列是假的...... (8认同)
  • @Steven,"真理"是_logic_中的一个概念,严格来说,它只适用于谓词:其他一切,_including_"布尔值",需要一个商定的映射,一个类型实例的_projection_逻辑概念.`all(ctr)`和`any(ctr)`为(所有项目都是真的)和"任何项目为真"的案例(罕见但非常有用)提供显式映射,`bool(ctr)`为最常见的"有任何项目"的情况.在'if`和`while`中_always_ oportally忽略`bool`调用的能力使得清晰,规律和简洁,没有任何牺牲. (4认同)
  • @Steven Schlansker:它更好,因为它的惯例; 容器的布尔值是否为非空.如果你要忽视惯例,就放弃; 都没了.您也可以反对"+"隐含地表示"添加". (4认同)

les*_*ana 14

is Empty一旦你理解了is操作员的作用,之所以没有,就会非常简单.

python手册:

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

这意味着some_sequence is Empty检查是否some_sequence是同一个对象Empty.这不能按照你的建议行事.

请考虑以下示例:

>>> a = []
>>> b = {}
Run Code Online (Sandbox Code Playgroud)

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

>>> a is Empty
True
>>> b is Empty
True
Run Code Online (Sandbox Code Playgroud)

但由于is运营商确实身份识别功能,意味着ab是相同的Empty.这反过来又一定意味着ab是相同的,但它们不是:

>>> a is b
False
Run Code Online (Sandbox Code Playgroud)

所以回答你的问题"为什么is Emptypython中没有?":因为is身份检查.

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

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

所以不要使用隐含的booleaness:

if saved:
  mess_up()
Run Code Online (Sandbox Code Playgroud)

我们有明确的空检查:

if not isempty(saved):
  mess_up()
Run Code Online (Sandbox Code Playgroud)

其中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)
Run Code Online (Sandbox Code Playgroud)

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


Vir*_*ras 5

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

我100%同意Alex wrt is Empty是unpythonic.

  • 永远不要这样做; 你强迫容器计算长度,这对于某些数据结构来说可能是昂贵的,当你想要知道的是它是否为空时. (6认同)
  • 通过相同的逻辑,`如果len(foo):`依赖于0显然是错误的事实;-p你必须从约定*开始*. (4认同)
  • @Glenn Maynard:"从不"是一个非常强硬的词.大多数时候,这是我们正在合作的清单.过早优化是万恶之源.3.可读性很重要. (4认同)
  • 1.除非您有特定的理由,否则不要假设您正在使用列表或任何特定类型.Duck打字是Python设计的基本概念.2.使用也很有效的公认惯例并不是过早优化.3.不相关,因为`if val:`是完全可读的. (2认同)