Python语法不一致?

7 投票
3 回答
1813 浏览
提问于 2025-04-16 17:01

我最近在阅读关于Python的特殊类方法的内容,发现有些方法的语法看起来有点奇怪或者不太一致。

比如,要从字典中获取所有的项目,你需要调用字典的类方法items()。

>>> my_dictionary.items()
[('name', 'Old Gregg'), ('Race', 'Scaly Man-Fish')]

但是,要知道字典中有多少个键,你就需要用len()这个函数,并把字典作为参数传进去。

>>> len(my_dictionary)
2

我一直以为像len()这样的函数其实并不是你调用它的那个类的一部分,因为它的语法看起来不太像,但在阅读了《Dive into Python》第五章后,我发现len()实际上是调用了字典的方法。

my_dictionary.__len__()

那么,为什么它和类似的方法不是像普通的类方法那样被调用呢?

my_dictionary.len()

难道有什么我不知道的约定吗?

3 个回答

1

这个区分很有用,因为它把使用和来源分开了。当你在给字典类编写扩展时,你知道你是在覆盖一些语言内置的功能。如果你真的想改变一个容器的行为,你需要重写 __len__()__getitem__() 等方法。

不过,作为使用别人代码的人,我就不需要担心这些了。如果我用 len(my_dictionary),我期待它的表现是稳定的,因为程序员应该知道怎么正确实现 __len__()。而且,任何人都可以随便写一个 my_dictionary.len() 方法,这样我就不太清楚它的表现了。

想了解更多关于下划线方法的信息,可以参考 http://www.siafoo.net/article/57,里面有很多相关的资料(第2.7.1节讲的是 __len__())。

1

我们不是在讲Java的事情。

在Python中,有很多方法可以用在对象上,只要这些对象实现了相关的API。

len() --> __len__()
str() --> __str__()
repr() --> __repr__()

除此之外:

为什么

my_dictionary.len()

要成为一个方法呢?

在JavaScript中,对象通过'length'属性来显示它们的大小,这样更自然,而不是使用一个方法……抱歉,并不是所有来自Java世界的东西都是好的,也不一定要在其他语言中存在。

12

Guido van Rossum这样解释:

(a) 对于某些操作,前缀表示法比后缀表示法更容易理解。前缀(还有中缀)操作在数学中有很长的历史,数学家们喜欢用能帮助他们思考问题的符号。比如,我们可以很轻松地把公式x*(a+b)改写成xa + xb,这比用面向对象的原始表示法要简单得多。

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

撰写回答