为什么Python的'len'函数比__len__方法更快?

15 浏览
0 Comments

为什么Python的'len'函数比__len__方法更快?

在Python中,len是一个用来通过调用对象的__len__方法来获取集合长度的函数:\n

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

\n所以我期望直接调用__len__()至少和len()一样快。\n

import timeit
setup = '''
'''
print (timeit.Timer('a="12345"; x=a.__len__()', setup=setup).repeat(10))
print (timeit.Timer('a="12345"; x=len(a)',      setup=setup).repeat(10))

\n演示链接\n但是以上代码运行结果表明len()更快。为什么呢?

0
0 Comments

Python中的`len()`函数比`__len__`方法更快,原因是`__len__`方法涉及到字典查找。这就引出了一个问题:`len`如何避免字典查找,对于不了解这个原理的人来说,这并不特别有用。解决方法是使用`len()`函数,而不是直接调用`__len__`方法。

0
0 Comments

Python的len()函数为什么比__len__()方法更快?

在《Python面向对象编程:构建健壮和可维护的面向对象Python应用程序和库》一书中,Steven F. Lott和Dusty Phillips解释了为什么len()函数比__len__()方法更高效。他们指出,大多数对象在应用len()函数时会调用一个名为__len__()的方法,该方法返回相同的值。所以调用len(myobj)实际上是调用了myobj.__len__()方法。

为什么我们应该使用len()函数而不是__len__()方法呢?显然,__len__()是一个特殊的双下划线方法,暗示我们不应该直接调用它。这一定有其原因。Python开发人员不会轻易做出这样的设计决策。

主要原因是效率。当我们调用一个对象的__len__()方法时,对象必须在其命名空间中查找该方法,并且如果该对象上定义了特殊的__getattribute__()方法(每当访问对象的属性或方法时都会调用该方法),还必须调用该方法。此外,__getattribute__()方法可能被编写成做一些巧妙的事情,例如拒绝我们访问特殊方法如__len__()!而len()函数则不会遇到这些问题。它实际上是在底层类上调用了__len__()方法,因此len(myobj)相当于MyObj.__len__(myobj)。

len()函数比__len__()方法更快的原因是,len()函数直接调用了底层类的__len__()方法,而不需要查找和调用其他特殊方法,从而提高了效率。

解决方法就是使用len()函数来获取对象的长度,而不是直接调用__len__()方法。这样可以避免不必要的查找和调用,提高代码的执行效率。

0
0 Comments

Python的`len()`函数比`__len__`方法快的原因是,`len()`函数不会查找`.__len__`属性,而是查找`tp_as_sequence`指针,该指针又具有`sq_length`属性。内置对象的`.__len__`属性间接地映射到同一个位置,并且正是这种间接性(加上属性查找)导致了更多的时间开销。对于Python定义的类,当请求`sq_length`时,`type`对象会查找`.__len__`方法。

解决这个问题的方法是,对于内置对象,可以直接使用`len()`函数而不是访问`.__len__`属性;对于Python定义的类,可以通过实现`.__len__`方法来提高性能。

下面是示例代码:

class MyClass:
    def __init__(self, data):
        self.data = data
    def __len__(self):
        return len(self.data)
my_obj = MyClass([1, 2, 3, 4, 5])
print(len(my_obj))  # 使用len()函数计算长度

通过实现`.__len__`方法,可以直接使用`len()`函数来计算类的长度,而不需要查找`sq_length`属性,从而提高了性能。

0