我知道python有一个len()函数,用于确定字符串的大小,但我想知道为什么它不是字符串对象的方法?
当前回答
Python是一种实用的编程语言,len()是一个函数而不是str, list, dict等的方法的原因是实用的。
len()内置函数直接处理内置类型:len()的CPython实现实际上返回PyVarObject C结构体中ob_size字段的值,该结构体表示内存中任何可变大小的内置对象。这比调用方法快得多——不需要进行属性查找。获取集合中的项数是一种常见操作,对于str、list、array等基本和不同的类型,必须有效地工作。数组等。
然而,为了提高一致性,当将len(o)应用于用户定义的类型时,Python调用o.__len__()作为回退。__len__, __abs__和Python数据模型中记录的所有其他特殊方法可以很容易地创建行为类似于内置的对象,从而实现我们称为“Pythonic”的具有表现力和高度一致性的api。
通过实现特殊的方法,你的对象可以支持迭代,重载中缀操作符,用块管理上下文等等。您可以将数据模型视为使用Python语言本身作为框架的一种方式,在该框架中可以无缝集成所创建的对象。
第二个原因是,读和写len(s)比s.len()更容易,这可以从Guido van Rossum的引用中得到支持。
表示法len(s)与带前缀表示法的一元运算符一致,如abs(n)。Len()比abs()使用得更频繁,而且它应该同样易于编写。
也可能有历史原因:在Python之前的ABC语言中(对Python的设计影响很大),有一个一元操作符写为#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是一种实用的编程语言,len()是一个函数而不是str, list, dict等的方法的原因是实用的。
len()内置函数直接处理内置类型:len()的CPython实现实际上返回PyVarObject C结构体中ob_size字段的值,该结构体表示内存中任何可变大小的内置对象。这比调用方法快得多——不需要进行属性查找。获取集合中的项数是一种常见操作,对于str、list、array等基本和不同的类型,必须有效地工作。数组等。
然而,为了提高一致性,当将len(o)应用于用户定义的类型时,Python调用o.__len__()作为回退。__len__, __abs__和Python数据模型中记录的所有其他特殊方法可以很容易地创建行为类似于内置的对象,从而实现我们称为“Pythonic”的具有表现力和高度一致性的api。
通过实现特殊的方法,你的对象可以支持迭代,重载中缀操作符,用块管理上下文等等。您可以将数据模型视为使用Python语言本身作为框架的一种方式,在该框架中可以无缝集成所创建的对象。
第二个原因是,读和写len(s)比s.len()更容易,这可以从Guido van Rossum的引用中得到支持。
表示法len(s)与带前缀表示法的一元运算符一致,如abs(n)。Len()比abs()使用得更频繁,而且它应该同样易于编写。
也可能有历史原因:在Python之前的ABC语言中(对Python的设计影响很大),有一个一元操作符写为#s,意思是len(s)。
这里的其他答案中遗漏了一些东西:len函数检查__len__方法是否返回一个非负整型。len是一个函数的事实意味着类不能重写此行为以避免检查。因此,len(obj)提供了obj.len()无法提供的安全级别。
例子:
>>> class A:
... def __len__(self):
... return 'foo'
...
>>> len(A())
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
len(A())
TypeError: 'str' object cannot be interpreted as an integer
>>> class B:
... def __len__(self):
... return -1
...
>>> len(B())
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
len(B())
ValueError: __len__() should return >= 0
当然,可以通过将len函数重新赋值为全局变量来“覆盖”它,但是这样做的代码显然比覆盖类中的方法的代码更可疑。
有一个len方法:
>>> a = 'a string of some length'
>>> a.__len__()
23
>>> a.__len__
<method-wrapper '__len__' of str object at 0x02005650>
吉姆对这个问题的回答可能会有所帮助;我复制在这里。引用Guido van Rossum的话:
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. /…/
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录