为啥 Python 中的字典和列表不继承 'len' 函数

Posted

技术标签:

【中文标题】为啥 Python 中的字典和列表不继承 \'len\' 函数【英文标题】:Why isn't the 'len' function inherited by dictionaries and lists in Python为什么 Python 中的字典和列表不继承 'len' 函数 【发布时间】:2008-09-17 14:43:18 【问题描述】:

示例:

a_list = [1, 2, 3]
a_list.len() # doesn't work
len(a_list) # works

Python(非常)面向对象,我不明白为什么“len”函数不被对象继承。 另外,我一直在尝试错误的解决方案,因为它对我来说似乎是合乎逻辑的解决方案

【问题讨论】:

函数不会被继承。方法是。您想继承谁的对象的len 方法? 这无关紧要,因为 len 只是调用 len 方法,所以同样的继承问题仍然适用。 @Eli 你的意思是__len__ 方法——所以将双下划线解释为粗体。 =) 【参考方案1】:

Guido 的解释是here:

首先,出于 HCI 的原因,我选择了 len(x) 而不是 x.len()(def __len__() 来得晚得多)。实际上有两个相互交织的原因,都是 HCI:

(a) 对于某些运算,前缀表示法比后缀读起来更好——前缀(和中缀!)运算在数学中有着悠久的传统,它喜欢视觉帮助数学家思考问题的符号。比较我们将 x*(a+b) 之类的公式重写为 x*a + x*b 的容易程度与使用原始 OO 表示法做同样事情的笨拙。

(b) 当我读到 len(x) 的代码时,我知道它是在询问某物的长度。这告诉我两件事:结果是一个整数,而参数是某种容器。相反,当我阅读 x.len() 时,我必须已经知道 x 是某种实现接口或继承自具有标准 len() 的类的容器。看看当一个没有实现映射的类有一个 get() 或 keys() 方法,或者不是文件的东西有一个 write() 方法时,我们偶尔会感到困惑。

用另一种方式说同样的话,我将“len”视为内置操作。我不想失去那个。 /…/

【讨论】:

对于那些不知道的人来说,HCI 代表人机界面。因此,当 Guido 说他出于“HCI 原因”做出决定时,他是说他认为这使代码更具可读性。 @Thomas:Python 使用| 进行按位或,就像 C 一样。 Guido 认为泛型函数比方法更好。头脑一片混乱。 ://【参考方案2】:

简短的回答:1) 向后兼容性和 2) 没有足够的差异让它真正重要。如需更详细的说明,请继续阅读。

这种操作的惯用 Python 方法是不打算直接调用的特殊方法。例如,要使x + y 为您自己的类工作,您编写一个__add__ 方法。要确保 int(spam) 正确转换您的自定义类,请编写 __int__ 方法。为了确保len(foo) 做一些有意义的事情,编写一个__len__ 方法。

这就是 Python 的一贯做法,我认为这对某些事情很有意义。特别是,这似乎是实现运算符重载的明智方法。至于其余的,不同的语言不同意;在 Ruby 中,您可以通过直接调用 spam.to_i 而不是说 int(spam) 来将某些内容转换为整数。

您说得对,Python 是一种极其面向对象的语言,而且必须在对象上调用外部函数来获取其长度似乎很奇怪。另一方面,len(silly_walks) 并不比silly_walks.len() 更繁重,Guido 说他实际上更喜欢它 (http://mail.python.org/pipermail/python-3000/2006-November/004643.html)。

【讨论】:

啊……终于明白了。 len() 实际上更像是一个运算符而不是一个函数。【参考方案3】:

事实并非如此。

但是,您可以这样做:

>>> [1,2,3].__len__()

3

__len__() 方法添加到类中是使len() 发挥作用的原因。

【讨论】:

【参考方案4】:

这种方式更适合其他语言。 python 中的约定是向对象添加__foo__ 特殊方法以使它们具有某些功能(而不是例如从特定的基类派生)。例如,一个对象是

如果有 __call__ 方法则可调用 如果它有 __iter__ 方法,则可迭代, 如果有__getitem____setitem__,则支持使用[] 访问。 ...

这些特殊方法之一是__len__,这使得它具有可通过len() 访问的长度。

【讨论】:

【参考方案5】:

也许您正在寻找__len__。如果该方法存在,则 len(a) 调用它:

>>> class Spam:
...   def __len__(self): return 3
... 
>>> s = Spam()
>>> len(s)
3

【讨论】:

【参考方案6】:

嗯,其实还有一个length方法,只是隐藏起来了:

>>> a_list = [1, 2, 3]
>>> a_list.__len__()
3

len() 内置函数似乎只是一个包装器,用于调用对象的隐藏 len() 方法。

不知道为什么他们决定以这种方式实施。

【讨论】:

【参考方案7】:

下面有一些很好的信息,说明为什么某些事物是函数而其他事物是方法。它确实会导致语言中的一些不一致。

http://mail.python.org/pipermail/python-dev/2008-January/076612.html

【讨论】:

以上是关于为啥 Python 中的字典和列表不继承 'len' 函数的主要内容,如果未能解决你的问题,请参考以下文章

Python3基础 __len__,__getitem__ 记录列表中元素访问的次数 定制不可变序列,下标字典

Python3基础 __len__,__getitem__ 记录列表中元素访问的次数 定制不可变序列,下标字典

Python 为啥list不能作为字典的key

Python怎样把2个列表合成为一个字典?

python的字符串列表字典和函数

python中列表,字典等必须要注意的事项