len()和..uuu len_uu()之间的区别?

2024-04-25 16:55:28 发布

您现在位置:Python中文网/ 问答频道 /正文

调用len([1,2,3])[1,2,3].__len__()之间有什么区别吗?

如果没有明显的差异,幕后又有什么不同的做法?


Tags: len差异区别
3条回答

可以认为len()大致相当于

def len(x):
    return x.__len__()

一个优点是它允许你写

somelist = [[1], [2, 3], [4, 5, 6]]
map(len, somelist) 

而不是

map(list.__len__, somelist)

或者

map(operator.methodcaller('__len__'), somelist)

不过,他们的行为略有不同。 例如在ints的情况下

>>> (1).__len__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__len__'
>>> len(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()

len是获取集合长度的函数。它通过调用对象的__len__方法来工作。__something__属性是特殊的,通常比肉眼看到的要多,通常不应该直接调用。

很早以前就决定了,得到某个东西的长度应该是一个函数,而不是一个方法代码,理由是len(a)的含义对于初学者来说是很清楚的,但是a.len()就不那么清楚了。当Python启动时,__len__甚至不存在,len是一个特殊的东西,它可以处理几种类型的对象。不管这种情况是否让我们完全有意义,它是在这里留下来的。

通常情况下,内置或运算符的“典型”行为是在所涉及的对象上调用(使用不同且更好的语法)合适的magic方法(名称类似于__whatever__)。通常,内置或运算符具有“附加值”(它可以根据所涉及的对象采用不同的路径)--在len__len__的情况下,它只是对magic方法缺少的内置进行了一点健全性检查:

>>> class bah(object):
...   def __len__(self): return "an inch"
... 
>>> bah().__len__()
'an inch'
>>> len(bah())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object cannot be interpreted as an integer

当您看到对内置的len的调用时,您肯定如果程序在该调用之后继续而不是引发异常,则该调用返回了一个整数、非负且小于2**31--当您看到对xxx.__len__()的调用时,您不确定(除了代码的作者不熟悉Python或不太擅长;-)。

除了简单的健全性检查和可读性之外,其他内置组件还提供了更多的附加值。通过统一地设计所有的Python,通过调用内置函数和使用操作符来工作,而不是通过调用魔术方法来工作,程序员就免去了记住哪种情况的负担。(有时会出现一个错误:在2.5之前,您必须在2.6中调用foo.next()——虽然这仍然适用于向后兼容,但您应该调用next(foo),在3.*中,magic方法正确命名为__next__,而不是“oops ey”next!-).

因此,一般规则应该是永远不要直接调用magic方法(但总是通过内置的方法间接调用),除非您确切地知道为什么需要这样做(例如,当您在子类中重写此类方法时,如果子类需要遵从必须通过显式调用magic方法来完成的超类)。

相关问题 更多 >