使用方法而不是函数时是否会对性能产生影响?

时间:2017-03-21 10:59:19

标签: python performance python-3.x class

我喜欢使用类和方法而不是裸函数。我想知道是否存在特定的性能影响(执行速度,内存使用或其他方面)。

快速测试显示两者表现同样良好:

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在一个案例中的使用比在另一个案例中使用的更多。

在使用类/方法而不是函数时是否会降低性能?

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

2 个答案:

答案 0 :(得分:4)

方法调用的开销实际上只是将function对象转换为method对象时,在属性访问(.)上对函数属性进行了实例访问。

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

所以,不,这里没有任何问题,开销很小,可以通过将方法分配给局部变量来完全消除:

meth = h.hello 
# use meth from now on

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

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

至于内存方面,方法应该比函数大一点,因为一个方法基本上包含一个函数作为其成员之一:

meth.__func__ # original function object

尽管如此,我无法想象由于引入了轻微的内存开销方法,您的应用程序会因此而陷入困境。

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

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

这不包括__func__属性,其中包含function个对象:

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

答案 1 :(得分:1)

调用方法obj.method(...)涉及属性访问(obj.method部分),这可能是一项非常重要且因此非常昂贵的操作。有关可能的属性访问方案的简要说明,请参见documentation of the descriptor protocol

  

属性访问的默认行为是获取,设置或删除   来自对象字典的属性。例如,a.x有一个   查找链以a.__dict__['x']开头,然后   type(a).__dict__['x'],并继续通过基类   type(a)不包括元类。

     

但是,如果查找的值是定义其中一个的对象   描述符方法,然后Python可以覆盖默认行为和   改为调用描述符方法。这种情况发生在哪里   优先级链取决于定义的描述符方法和   他们是如何被召唤的。

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