为什么Python代码使用len()函数而不是length方法?

为什么Python代码使用len()函数而不是length方法?,python,function,oop,methods,string-length,Python,Function,Oop,Methods,String Length,我知道python有一个len()函数,用于确定字符串的大小,但我想知道为什么它不是string对象的方法 更新 好吧,我意识到我错得很尴尬\uu len\uu()实际上是字符串对象的方法。看到Python中的面向对象代码在字符串对象上使用len函数似乎很奇怪。此外,将\uuu len\uuu视为名称而不仅仅是len也很奇怪。有一种len方法: met% python -c 'import this' | grep 'only one' There should be one-- and pre

我知道python有一个
len()
函数,用于确定字符串的大小,但我想知道为什么它不是string对象的方法

更新
好吧,我意识到我错得很尴尬
\uu len\uu()
实际上是字符串对象的方法。看到Python中的面向对象代码在字符串对象上使用len函数似乎很奇怪。此外,将
\uuu len\uuu
视为名称而不仅仅是len也很奇怪。

有一种
len
方法:

met% python -c 'import this' | grep 'only one'
There should be one-- and preferably only one --obvious way to do it.
>>> a = 'a string of some length'
>>> a.__len__()
23
>>> a.__len__
<method-wrapper '__len__' of str object at 0x02005650>
>a='某个长度的字符串'
>>>a.______;)
23
>>>a.。uu len__

字符串确实有一个长度方法:
\uuu len\uuu()

Python中的协议是在具有长度的对象上实现此方法,并使用内置函数为您调用此方法,类似于在可iterable的对象上实现
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

有关更多信息,请参阅

这里有一本关于Python协议的好书:

Jim对的回答可能会有所帮助;我复制到这里。引用Guido van Rossum的话:

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

(a) 对于某些运算来说,前缀表示法的可读性比后缀表示法要好——前缀(和中缀!)运算在数学中有着悠久的传统,它喜欢在视觉上帮助数学家思考问题的表示法。将我们将x*(a+b)这样的公式改写为xa+xb的简单方法与使用原始OO表示法做同样事情的笨拙方法进行比较

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

用另一种方式说同样的话,我认为‘len’是一种内置的操作。我不想失去它/

不是吗

>>> "abc".__len__()
3
你也可以说

>> x = 'test'
>> len(x)
4

使用Python 2.7.3.

Python是一种实用的编程语言,
len()
作为函数而不是
str
list
dict
等的方法的原因是实用的

len()
内置函数直接处理内置类型:
len()
的CPython实现实际上返回中表示内存中任何可变大小内置对象的
ob\u size
字段的值。这比调用方法快得多——不需要进行属性查找。获取集合中的项目数是一项常见的操作,对于诸如
str
list
array.array
等基本和多样的类型,必须有效地工作

但是,为了提高一致性,当将
len(o)
应用于用户定义的类型时,Python调用
o.\uu len\uu()
,作为一种后备方法<代码>\uuuu len\uuuuu
\uuuuu abs\uuuuu
以及中记录的所有其他特殊方法使创建行为类似内置的对象变得容易,从而实现了我们称为“Pythonic”的表现力强、高度一致的API

通过实现特殊方法,您的对象可以支持迭代、重载中缀运算符、使用
块管理
中的上下文等。您可以将数据模型视为使用Python语言本身作为框架的一种方式,在该框架中,您创建的对象可以无缝集成

第二个原因,由Guido van Rossum like的引用支持,是读写
len
s.len()
更容易

表示法
len(s)
与带有前缀表示法的一元运算符一致,如
abs(n)
len()
的使用频率高于
abs()
,而且它应该同样易于编写


可能还有一个历史原因:在Python之前的ABC语言中(在其设计中非常有影响力),有一个一元运算符被写成
#s
,这意味着
len(s)
这里有一些很好的答案,所以在我给出我自己的答案之前,我想强调一些宝石(不是红宝石双关语)我在这里读过

  • Python不是一种纯粹的OOP语言——它是一种通用的多范式语言,允许程序员使用他们最熟悉的范式和/或最适合他们的解决方案的范式
  • Python具有一流的函数,因此
    len
    实际上是一个对象。另一方面,Ruby没有一流的函数。因此,
    len
    函数对象有自己的方法,您可以通过运行
    dir(len)
    来检查这些方法
如果您不喜欢在自己的代码中使用这种方式,那么使用首选方法重新实现容器对您来说是微不足道的(请参见下面的示例)


这里剩下的答案中缺少了一些东西:
len
函数检查
\uuuu len\uuu
方法是否返回非负的
int
len
是一个函数,这意味着类不能重写此行为以避免检查。因此,
len(obj)
提供了
obj.len()
无法提供的安全级别

例如:

>>A类:
...     定义(自我):
...         返回“foo”
...
>>>len(A())
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
len(A())
类型错误:“str”o
>>> class List(list):
...     def len(self):
...         return len(self)
...
>>> class Dict(dict):
...     def len(self):
...         return len(self)
...
>>> class Tuple(tuple):
...     def len(self):
...         return len(self)
...
>>> class Set(set):
...     def len(self):
...         return len(self)
...
>>> my_list = List([1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'])
>>> my_dict = Dict({'key': 'value', 'site': 'stackoverflow'})
>>> my_set = Set({1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'})
>>> my_tuple = Tuple((1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'))
>>> my_containers = Tuple((my_list, my_dict, my_set, my_tuple))
>>>
>>> for container in my_containers:
...     print container.len()
...
15
2
15
15