Python len()和._ulen__u;()之间的区别?

Python len()和._ulen__u;()之间的区别?,python,Python,调用len([1,2,3])或[1,2,3]之间有什么区别吗 如果没有明显的差异,在幕后会有什么不同的做法?len是一个获取集合长度的函数。它通过调用对象的方法来工作\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu 在很久以前的某个时候,人们决定获取某个东西的长度应该是一个函数,而不是一个方法代码,理由是len(a)的意思对于初学者来说是很清楚的,但是a.len()就不那么清楚

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


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

len
是一个获取集合长度的函数。它通过调用对象的
方法来工作<代码>\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

在很久以前的某个时候,人们决定获取某个东西的长度应该是一个函数,而不是一个方法代码,理由是
len(a)
的意思对于初学者来说是很清楚的,但是
a.len()
就不那么清楚了。当Python启动时,
\uuu len\uuu
甚至不存在,
len
是一种特殊的东西,可以处理几种类型的对象。不管这种情况是否完全有意义,它都将继续存在。

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

def len(x):
    return x.__len__()
一个优点是它可以让你写像这样的东西

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

map(list.__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()
>>>(1)。\uu len
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:“int”对象没有属性“\uuuu len\uuuu”
>>>len(1)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:类型为“int”的对象没有len()

通常情况下,内置or运算符的“典型”行为是(使用不同且更好的语法)在所涉及的对象上调用合适的魔术方法(名称为
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu等)。通常,内置or运算符具有“附加值”(它能够根据所涉及的对象选择不同的路径)——在
len
vs
\uuuuu len\uuuu
的情况下,只是对魔术方法中缺少的内置对象进行了一点健全性检查:

>>> 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
>>类bah(对象):
...   定义长度(self):返回“一英寸”
... 
>>>呸()。______()
“一英寸”
>>>len(bah())
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:“str”对象不能解释为整数
当您看到对内置
len
的调用时,您可以确定如果程序在此之后继续而不是引发异常,则调用已返回一个整数、非负,并且
,您可以检查:

嗯,
len(s)
是一个内置的Python方法,它返回对象的长度。现在,
\uu len\uu()
是一个特殊的方法,由
len(s)
方法在内部调用,以返回对象的长度

因此,当我们调用
len(s)
方法时,
s.\uu len\uuu()
就是在幕后实际发生的事情来计算长度

Python
len()
函数可以解释为:

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

看,我是Python初学者用户(不是初学者程序员认为的那样),我不确定“当您看到对len内置函数的调用时,您可以确定,如果程序在此之后继续运行,而不是引发异常”。我试过这样做:
def len(x):返回“我是一个字符串”。print(len(42))print(len([1,2,3])
它将
I am string
打印了两次。你能再解释一下吗?@DarekNędza这与上述内容无关,这是关于内置透镜的。您刚刚定义了len函数,它当然可以返回您想要的任何结果。OP谈到了内置函数len,它在考虑中的对象上调用
\uuuLen\uUn
特殊方法(而不是函数)。@Veky我如何确定我调用的是内置函数
len
,而不是其他碰巧同名的函数(如我的示例中的函数-
len
)。没有类似“您正在重新定义内置函数len”之类的警告。在我看来,我不能确定Alex在回答中说了什么。Alex明确地说,如果你打电话给builtin,那么你肯定…\。他没说要确定你打电话给builtin。但是如果您想知道这一点,您可以:
len in vars(\uuuu builtins\uuuu).values()
。遗憾的是,这是Python中缺少通用对象基类的另一个例子。句法语境转换一直都很疯狂。在某些情况下,使用下划线方法是常见的习惯用法,在另一些情况下,应该使用函数之类的方法来完成许多对象的通用操作。这也很奇怪,因为许多对象对len没有语义用途。有时对象模型更像C++,厨房脏兮兮……我假设你是指<代码>运算符。方法调用程序< /> >而不是<代码>运算符。
>>> 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
def len(s):
    return s.__len__()