Mik*_*ham 91
len
是一个获取集合长度的函数.它通过调用对象的__len__
方法来工作.__something__
属性是特殊的,通常不仅仅是满足眼睛,通常不应该直接调用.
在很久以前就确定了某些东西的长度应该是一个函数,而不是一个方法代码,推断len(a)
初学者的意思是明确的,但a.len()
不会那么清楚.当Python启动__len__
时甚至不存在,并且len
是一种特殊的东西,它适用于几种类型的对象.无论这种情况离开我们是否完全合理,它都会留下来.
Ale*_*lli 63
通常情况下,内置或运算符的"典型"行为是__whatever__
在所涉及的对象上调用(具有不同且更好的语法)合适的魔术方法(名称相似的方法).通常内置或运算符具有"附加值"(它可以根据所涉及的对象采用不同的路径) - 在len
vs 的情况下__len__
,它只是对内置的一些完整性检查魔法:
>>> 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
Run Code Online (Sandbox Code Playgroud)
当你看到对len
内置函数的调用时,你确定,如果程序在此之后继续而不是引发异常,则调用返回一个整数,非负数,小于2**31 - 当你看到一个电话xxx.__len__()
,你没有把握(除了代码的作者要么不熟悉Python,要么根本没有好;-).
除了简单的健全性检查和可读性之外,其他内置函数还提供了更多附加值.通过调用内置函数和使用运算符来统一设计所有Python,从不通过调用魔术方法,程序员可以免于记住哪种情况的负担.(有时会出现错误:直到2.5,你必须调用foo.next()
- 在2.6中,虽然这仍然适用于向后兼容性,你应该调用next(foo)
,然后3.*
,魔术方法被正确命名__next__
而不是"oops-ey" next
! - ).
因此,一般规则应该是永远不要直接调用魔术方法(但总是通过内置方式间接调用),除非你确切知道为什么需要这样做(例如,当你在子类中重写这样的方法时,如果子类需要遵循必须通过对magic方法的显式调用来完成的超类.
Joh*_*ooy 24
你可以认为len()大致相当于
def len(x):
return x.__len__()
Run Code Online (Sandbox Code Playgroud)
一个优点是它允许你写出类似的东西
somelist = [[1], [2, 3], [4, 5, 6]]
map(len, somelist)
Run Code Online (Sandbox Code Playgroud)
代替
map(list.__len__, somelist)
Run Code Online (Sandbox Code Playgroud)
要么
map(operator.methodcaller('__len__'), somelist)
Run Code Online (Sandbox Code Playgroud)
但是行为略有不同.例如,在整数的情况下
>>> (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()
Run Code Online (Sandbox Code Playgroud)
小智 5
您可以查看Pythond 文档:
>>> class Meta(type):
... def __getattribute__(*args):
... print "Metaclass getattribute invoked"
... return type.__getattribute__(*args)
...
>>> class C(object):
... __metaclass__ = Meta
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print "Class getattribute invoked"
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
Run Code Online (Sandbox Code Playgroud)