2017-03-21 22 views
3

我喜欢使用类和方法而不是裸函数。我想知道是否有特定的性能影响(执行速度或内存使用情况或其他方面)。使用方法而不是函数会对性能产生影响吗?

快速测试显示,这两个同样表现出色:

import timeit 

class Hello: 
    def hello(self): 
     x = 9 * 8 + 3**5 

def world(): 
    x = 9 * 8 + 3 ** 5 

print(timeit.timeit(world, number=10000000)) 
h = Hello() 
print(timeit.timeit(h.hello, number=10000000)) 
# 0.8460009839758439 
# 0.8781686117747095 

在其他测试中,我没有看到正在使用的RAM更在一种情况下比其他。

是否存在使用类/方法而不是函数时性能会降低的特定情况?

注:我想专注于代码的性能,而不是美学方面

+0

尝试将它们包装在lambda中并再次测试。 –

回答

4

方法调用的开销实际上只是function对象为method对象转换时属性的访问(.)上它由一个实例创建的函数属性。

除此之外,函数的调用也是类似的,为方法隐含插入一个额外参数(self)。

所以,没有,真的没有任何顾虑到这里,开销小,可以通过分配方法的局部变量完全消除:

meth = h.hello 
# use meth from now on 

(编辑:在Python 3.7new op-codes其中引入的基本上否定了将h.hello分配到本地名称的好处,查找方法的速度更快:-)

如果您正在寻找瓶颈,那么您应该查找其他地方。 Python的动态解释确实使这些问题变得迂腐。


至于内存方面,方法应该比功能稍大由于基本上含有一个函数作为它的一个成员的方法:

meth.__func__ # original function object 

尽管这样,我无法想象一个由于内存开销方法引入而导致应用程序窒息的场景。

在CPython的,例如,大约64个字节根据getsizeof添加了用于绑定的方法对象:

>>> getsizeof(Foo().foo) 
64 

这不是计数__func__属性,其中包含function对象:

>>> getsizeof(Foo().foo.__func__) 
136 
1

调用方法obj.method(...)涉及属性访问(obj.method部分),这可能是一个不平凡的因此成本很高的操作。一个可能的属性的访问情况的简要描述在documentation of the descriptor protocol发现:

的访问属性的默认行为是获取,设置或删除 从对象的字典中的属性。例如,a.x具有 查找链,其从a.__dict__['x']开始,然后是 type(a).__dict__['x'],并且继续通过除元类之外的基类 type(a)

但是,如果查找的值是定义描述符方法之一的对象,则Python可能会覆盖默认行为,而代之以调用描述符方法。在 优先级链中发生这种情况取决于定义了哪些描述符方法,以及如何调用这些方法 。

只有在属性访问完成后,调用结果可调用对象与调用自由函数几乎没有区别。但是,请注意,在您的基准测试中,属性访问的开销(即看起来无害的表达式h.hello后面的操作)未被测量(尽管在您的示例中它应该非常小)。

相关问题