我喜欢使用类和方法而不是裸函数。我想知道是否存在特定的性能影响(执行速度,内存使用或其他方面)。
快速测试显示两者表现同样良好:
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 :(得分: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
背后的操作,不会被测量(尽管在您的示例中它应该非常小)。