【问题标题】:Why doesn't len(None) return 0?为什么 len(None) 不返回 0?
【发布时间】:2015-07-27 06:00:01
【问题描述】:

None 在 Python 中是一个对象。

>>> isinstance(None, object)
True

因此它可以使用像 __str__() 这样的函数

>>> str(None)
'None'

但是为什么它对 __len__() 不做同样的事情呢?

>>> len(None)
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    len(None)
TypeError: object of type 'NoneType' has no len()

这似乎是 Pythonic,就像 if list 是可以接受的一样,即使变量是 None 而不仅仅是一个空列表。

是否存在使len(None) 的使用更成问题的情况?

【问题讨论】:

  • 因为None 没有__len__;不是Sized
  • @jonrsharpe 但它可能只是添加了一个无论如何都返回 0 的函数。
  • 可以,但没有多大意义。为什么一个对象有一个长度,除非它是一个对象的集合?
  • 如果您有可能获得Nonelist 的情况,您应该先测试if what_i_think_is_a_list is not None:,然后再将其视为列表。所有内置类型都有真实性,但有很多操作在 None 上毫无意义(你也不能迭代它)。为None 实现len 只会隐藏应捕获的错误。
  • None 没有长度,原因与整数和浮点数没有长度相同。 这不是一个集合。它不能变长或变短。

标签: python nonetype


【解决方案1】:

如果您有一个可能返回None 的项目,您可以使用len(None or ''),它将返回return 0 或第一个项目的长度(如果它是not None)。

【讨论】:

    【解决方案2】:

    你提到你想要这个:

    因为当函数返回 None 而不是列表时,它经常作为错误出现

    大概,你有这样的代码:

    list_probably = some_function()
    for index in range(len(list_probably)):
        ...
    

    并且正在获得:

    TypeError: object of type 'NoneType' has no len()
    

    注意以下几点:

    • len 用于确定集合的长度(例如listdictstr - 这些是Sized 对象)。 不是用于将任意对象转换为整数 - 例如,它也不适用于 intbool
    • 如果None 是可能的,您应该明确地测试if list_probably is not None。使用例如if list_probably 会将 None 和空列表 [] 视为相同,这可能不是正确的行为;和
    • 通常有更好的方法来处理range(len(...)) 的列表,例如for item in list_probably,使用zip

    None 实现len 只会隐藏错误,其中None 被错误地处理,就像其他一些对象一样 - 每个the Zen of Python (import this):

    错误不应该默默地过去。

    同样for item in None 会失败,但这并不意味着实现None.__iter__ 是一个好主意!错误是一件好事 - 它们可以帮助您快速找到程序中的问题。

    【讨论】:

      【解决方案3】:

      len 仅对对象集合有意义 - None 不是集合。

      【讨论】:

      • 说它总是返回 0 是否比 None 的真实性(或虚假性)更有意义?
      • @SuperBiasedMan 是的,它没有多大意义。问问自己,红色的长度是 0 吗?
      • @SuperBiasedMan 是的!整数也没有长度,但有真实性 - 请参阅docs.python.org/2/library/stdtypes.html#truth-value-testing。另请注意,您通常应该通过 identity 而不是 truthiness 来测试 None
      • @jonrsharpe 这一点特别好。我想我在考虑 len() 只是返回一个表示变量的 int 值,而不是显式地作为集合的计数。 (我也指的是用真实性测试一个列表,当你有 None 而不是列表时它会处理这种情况)
      猜你喜欢
      • 2021-06-30
      • 2013-05-30
      • 2013-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-29
      • 2015-06-18
      相关资源
      最近更新 更多