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

更新

好吧,我意识到我犯了一个令人尴尬的错误。 __len__() 实际上是一个字符串对象的方法。在 Python 中看到在字符串对象上使用 len 函数的面向对象代码似乎很奇怪。另外,看到也很奇怪 __len__ 作为名称而不仅仅是 len。

有帮助吗?

解决方案

字符串有一个长度方法: __ len __()

Python中的协议是在具有长度的对象上实现此方法并使用内置的 len() 函数,它为你调用它,类似于你实现 __ iter __()的方式并在可迭代的对象上使用内置的 iter()函数(或者在幕后调用方法)。

有关详细信息,请参阅模拟容器类型

以下是关于Python协议主题的精彩读物: Python和最小惊讶原则

其他提示

Jim对这个问题的回答可能有所帮助;我把它复制在这里。引用Guido van Rossum:

  

首先,由于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‘作为内置操作。我不想失去那个。 /… /

len 方法:

>>> a = 'a string of some length'
>>> a.__len__()
23
>>> a.__len__
<method-wrapper '__len__' of str object at 0x02005650>

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

len()内置函数直接处理内置类型: len()的CPython实现实际上返回 ob_size的值 PyVarObject C struct 中的字段>表示内存中任何可变大小的内置对象。这比调用方法更快 - 不需要进行属性查找。获取集合中的项目数是一项常见操作,必须有效地处理 str list array.array 等。

但是,为了提高一致性,在将 len(o)应用于用户定义的类型时,Python将 o .__ len __()作为后备调用。 __ len __ __ abs __ 以及中记录的所有其他特殊方法Python数据模型可以轻松创建行为类似于内置插件的对象,从而实现我们称之为“Pythonic”的富有表现力且高度一致的API。

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

第二个原因,由Guido van Rossum的引言支持,如这个,它比更容易读写 len(s) s.len()

符号 len(s)与带有前缀表示法的一元运算符一致,如 abs(n) len()的使用方式比 abs()更常用,并且它应该像编写一样容易。

可能还有一个历史原因:在Python之前的ABC语言中(并且在设计中非常有影响力),有一个一元运算符被写为 #s ,这意味着 len (S)

met% python -c 'import this' | grep 'only one'
There should be one-- and preferably only one --obvious way to do it.

这里有一些很好的答案,所以在我给出自己的答案之前,我想强调一下我在这里读到的一些宝石(没有红宝石双关语的意思)。

  • Python 不是一种纯粹的 OOP 语言——它是一种通用的多范式语言,允许程序员使用他们最熟悉的范式和/或最适合他们的解决方案的范式。
  • Python 具有一流的函数,因此 len 实际上是一个对象。另一方面,Ruby 没有一流的函数。所以 len 函数对象有它自己的方法,您可以通过运行来检查 dir(len).

如果您不喜欢它在您自己的代码中的工作方式,那么您可以使用您喜欢的方法重新实现容器(请参见下面的示例)。

>>> 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

你也可以说

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

使用Python 2.7.3。

不是吗?

>>> "abc".__len__()
3
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top