python len()和len()的区别__len__()?

new9mtju  于 2023-04-28  发布在  Python
关注(0)|答案(6)|浏览(188)

调用len([1,2,3])[1,2,3].__len__()有什么区别吗?
如果没有明显的区别,那么幕后的不同之处是什么?

z4bn682m

z4bn682m1#

len是一个获取集合长度的函数。它通过调用对象的__len__方法来工作。__something__属性是特殊的,通常比我们看到的要多,一般不应该直接调用。
在很久以前的某个时候,人们决定获取某个东西的长度应该是一个函数,而不是一个方法代码,理由是len(a)的含义对初学者来说很清楚,但a.len()就不那么清楚了。当Python开始的时候,__len__甚至还不存在,len是一个特殊的东西,可以处理一些类型的对象。不管这件事留给我们的情况是否完全合理,它都将继续存在。

xtupzzrd

xtupzzrd2#

通常情况下,内置or运算符的“典型”行为是在所涉及的对象上调用(使用不同的更好的语法)合适的魔术方法(名称为__whatever__的方法)。通常,内置的or运算符具有“附加值”(它能够根据所涉及的对象选择不同的路径)--在len__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

当您看到对len内置代码的调用时,您肯定,如果程序在此之后继续而不是引发异常,则返回了一个非负整数和<= sys.maxsize--当您看到对xxx.__len__()的调用时,您不确定(除了代码的作者不熟悉Python或不太好;- ).
除了简单的健全性检查和可读性之外,其他内置程序还提供了更多附加值。通过统一地设计所有Python,使其通过调用内置函数和使用运算符来工作,而不是通过调用魔术方法,程序员可以免除记住哪种情况是哪种情况的负担。(有时会出现错误:在2.5之前,你必须调用foo.next()--在2中。6,虽然这仍然可以向后兼容,但您应该调用next(foo),在3.*中,魔术方法正确命名为__next__而不是“oops-ey”next!- ).
因此,一般的规则应该是永远不要直接调用魔术方法(但总是通过内置函数间接调用),除非你确切地知道为什么需要这样做(例如:例如,当你在子类中重写这样的方法时,如果子类需要服从超类,这必须通过显式调用魔术方法来完成)。

vc9ivgsu

vc9ivgsu3#

可以将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)

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

>>> (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()
7gcisfzg

7gcisfzg4#

您可以查看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
biswetbf

biswetbf5#

len(s)是一个内置的Python方法,它返回对象的长度。现在__len__()是一个特殊的方法,由len(s)方法内部调用,以返回对象的长度。
因此,当我们调用len(s)方法时,s.__len__()实际上是在幕后发生的,以计算长度。
Python len()函数可以解释为:

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

参考

8cdiaqws

8cdiaqws6#

一条附加评论:
len(c)c.__len__()可以返回不同的值。这种情况通常发生在我们修改示例c__len__函数时。

>>> class C:
...     def __len__(self):
...         return 10
...
>>> c = C()
>>> c.__len__ = lambda: 3
>>> len(c)                    # C's __len__ invoked
10
>>> type(c).__len__(c)        # C's __len__ invoked
10
>>> c.__len__()               # c's __len__ invoked
3

相关问题