为什么Python中的字典和列表无法继承'len'函数

时间:2020-03-05 18:59:02  来源:igfitidea点击:

例子:

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

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

解决方案

回答

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

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

回答

事实并非如此。

但是,我们可以执行以下操作:

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

3

在类中添加__len __()方法是使len()神奇发挥作用的原因。

回答

好吧,实际上有一个length方法,它只是隐藏的:

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

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

尽管不确定为什么他们决定以这种方式实现事物。

回答

Guido的解释在这里:

First of all, I chose len(x) over x.len() for HCI reasons (def __len__() came much later). There are two intertwined reasons actually, both HCI:
  
  (a) For some operations, prefix notation just reads better than postfix — prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem. Compare the easy with which we rewrite a formula like x*(a+b) into x*a + x*b to the clumsiness of doing the same thing using a raw OO notation.
  
  (b) When I read code that says len(x) I know that it is asking for the length of something. This tells me two things: the result is an integer, and the argument is some kind of container. To the contrary, when I read x.len(), I have to already know that x is some kind of container implementing an interface or inheriting from a class that has a standard len(). Witness the confusion we occasionally have when a class that is not implementing a mapping has a get() or keys() method, or something that isn’t a file has a write() method.
  
  Saying the same thing in another way, I see ‘len‘ as a built-in operation. I’d hate to lose that. /…/

回答

简短的答案是: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)。

回答

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

  • 如果具有__call__方法,则可以调用
  • 如果有一个__iter__方法,则是可迭代的,
  • 如果[]具有__getitem____setitem__,则支持通过[]访问。
  • ...

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

回答

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

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