为什么sorted()和reversed()是内置函数而不是序列的方法?

4

我现在正在学习Python 3.3,我想知道一些用于管理集合/可迭代对象的函数(例如sorted()reversed())为什么是内置的,而有些则作为集合对象的方法实现?我可以使用方法append()将项目添加到列表中,但要获取其长度,则应使用内置函数len()。对我来说,这似乎不一致,但我认为我可能错过了新语言中的某些要点。


1
sorted 接受任何可迭代对象作为其第一个参数。与列表方法 sort 相对应。 - cdarke
我应该先阅读常见问题解答:https://docs.python.org/3/faq/design.html#why-does-python-use-methods-for-some-functionality-e-g-list-index-but-functions-for-other-e-g-len-list :) - artvolk
1个回答

5
简短的回答是,这些决定是基于人类原因而非技术原因做出的。
关于len()和obj.length()的区别的推理,由Guido van Rossum(Python的有恩之人)在这里进行了解释:
首先,我选择len(x)而不是x.len()是出于HCI原因(def __len__()要晚得多)。实际上有两个交织在一起的原因,都是HCI:
(a) 对于某些操作,前缀符号比后缀符号更易读 - 前缀(和中缀!)操作在数学中有着悠久的传统,数学喜欢那些视觉上帮助数学家思考问题的符号。将像x *(a + b)这样的公式重写为x * a + x * b与使用原始OO符号做同样的事情的笨拙程度相比较。
(b) 当我阅读代码说len(x)时,我知道它正在请求某些东西的长度。这告诉我两件事:结果是整数,参数是某种容器。相反,当我读到x.len()时,我必须已经知道x是实现接口或从具有标准len()的类继承的某种容器。看看我们偶尔遇到的混乱,当一个不实现映射的类有一个get()或keys()方法,或者一些不是文件的东西有一个write()方法。
他还解释了为什么sorted()和reversed()不是方法:
还要注意,许多函数是根据非正式接口定义的;例如,reversed适用于任何支持随机访问项并具有已知长度的内容。在实践中,将max、sum、map、any、in和其他函数和运算符作为内置函数和运算符实现实际上比将它们作为需要支持它们的每种类型的方法实现要少写代码。

关于sorted()reversed()的最后一段是一个好观点,但为什么他们不使用像mixins或者抽象方法这样的东西呢? - artvolk
只是为了澄清一下:我来自C#,在那里集合类和接口不是内置于语言本身的。 - artvolk
1
@artvolk:这是一种语言设计决策。在C#和Java中,混合和抽象方法运作良好,但Python更依赖于鸭子类型。如果您想让一个新的集合以某种方式运作,只需添加一些方法,然后实例就可以被各种内置函数使用。 - Simeon Visser
至少在这些设计决策做出时是这样的。现在我们有了ABCs,reverse()__reversed __()实际上是MutableSequenceSequence的mixin方法。sorted仍然没有定制的点。也许因为如果设置了key参数,容器基本上无法对该过程做出贡献。 - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接