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

253 投票
7 回答
190996 浏览
提问于 2025-04-11 18:21

7 个回答

43

Python是一种实用的编程语言,为什么len()是一个函数而不是strlistdict等的一个方法,这个原因也是基于实用性。

len()这个内置函数直接处理内置类型:在CPython的实现中,len()实际上返回的是PyVarObject这个C结构体中ob_size字段的值,这个结构体代表了内存中任何可变大小的内置对象。这种方式比调用一个方法要快得多——因为不需要查找属性。获取一个集合中项目的数量是一个常见的操作,对于像strlistarray.array这样的基本和多样化的类型,必须高效地工作。

不过,为了保持一致性,当你对用户自定义类型使用len(o)时,Python会调用o.__len__()作为备用。__len____abs__以及其他在Python数据模型中记录的特殊方法,使得创建像内置对象一样行为的对象变得简单,从而实现我们称之为“Pythonic”的表达性和高度一致的API。

通过实现特殊方法,你的对象可以支持迭代、重载中缀运算符、管理with块中的上下文等等。你可以把数据模型看作是使用Python语言本身作为框架,这样你创建的对象可以无缝集成。

第二个原因,受到Guido van Rossum的引用支持,比如这个,是len(s)s.len()更容易阅读和书写。

这种len(s)的写法与前缀表示法的一元运算符一致,比如abs(n)len()的使用频率远高于abs(),所以它应该写得更简单。

可能还有一个历史原因:在Python之前的ABC语言(对Python的设计影响很大)中,有一个一元运算符写作#s,它的意思是len(s)

117

Jim对这个问题的回答可能会对你有帮助;我把它复制过来了。引用Guido van Rossum的话:

首先,我选择len(x)而不是x.len()是出于人机交互的考虑(def __len__()是在后来才出现的)。其实有两个相互关联的原因,都是关于人机交互的:

(a) 对于某些操作,前缀表示法比后缀表示法更容易理解——前缀(和中缀!)操作在数学中有着悠久的传统,数学家喜欢那些能帮助他们思考问题的符号。比如,我们把公式x*(a+b)改写成x*a + x*b时,前者显得简单多了,而用面向对象的原始表示法来做同样的事情就显得笨拙。

(b) 当我看到代码写着len(x)时,我知道这是在询问某个东西的长度。这让我明白两件事:结果是一个整数,参数是某种容器。相反,当我看到x.len()时,我得先知道x是什么类型的容器,它实现了某个接口或者继承了一个有标准len()的方法的类。想想看,当一个类没有实现映射却有get()或keys()方法,或者某个不是文件的东西却有write()方法时,我们就会感到困惑。

换句话说,我把‘len’看作是一个内置操作。我不想失去这个功能。/…/

201

字符串确实有一个长度的方法:__len__()

在Python中,规定是要在那些有长度的对象上实现这个方法,然后使用内置的 len() 函数,这个函数会帮你调用这个方法。这个过程有点像你在可迭代对象上实现 __iter__() 方法,然后使用内置的 iter() 函数(或者这个方法在后台被自动调用)。

想了解更多信息,可以查看 模拟容器类型

关于Python中的协议,这里有一篇不错的文章: Python与最小惊讶原则

撰写回答