【发布时间】:2017-12-07 12:17:18
【问题描述】:
我有几个在其中使用self 的实例方法,但只在几个地方。
我可以直接将对象传递给这些方法,并将它们设为staticmethods。这会消耗更少的内存吗?
【问题讨论】:
标签: python python-3.x memory memory-management static-methods
我有几个在其中使用self 的实例方法,但只在几个地方。
我可以直接将对象传递给这些方法,并将它们设为staticmethods。这会消耗更少的内存吗?
【问题讨论】:
标签: python python-3.x memory memory-management static-methods
您在这里进行微优化,没有任何好处。
是的,常规方法涉及一个新的 method 对象,该对象被创建用于处理函数和实例之间的绑定,但这只是一点内存(2 个指针加上一些 Python 元数据)仅在持续时间内使用调用或存储绑定方法 *。 staticmethod 对象不会创建新的方法对象,但这会被staticmethod 对象所需的内存量抵消:
>>> import sys
>>> class Foo:
... def bar(self): pass
... @staticmethod
... def staticbar(): pass
...
>>> sys.getsizeof(Foo().bar) # bound method object size
64
>>> sys.getsizeof(Foo.__dict__['staticbar']) # staticmethod size
56
所以使用staticmethod 对象可以节省 8 个字节(在 Mac OS X 上,在另一个操作系统上字节数可能略有不同),但您通常不会保留绑定方法(您'd 使用instance.method(),它创建方法对象,然后在调用后再次丢弃它)。
因此,除非您存储大量绑定方法,否则这并不足以证明通过在任何地方手动传递实例来使您的代码不可读。
* 请注意,从 Python 3.7 开始,对于常见情况,Python 甚至不再创建方法对象。见Optimisations section of the 3.7 What's New notes:
由于避免创建绑定方法实例的字节码更改,方法调用现在提高了 20%。
这适用于<expr>.attribute_name(...) 调用序列,因此在相同的整体表达式中,属性名称查找直接后跟调用,前提是仅使用位置参数。生成特殊字节码,验证attribute_name 解析为类上的方法名称,然后直接调用底层函数,并在前面加上<expr> 的结果。 Python 使用LOAD_METHOD 后跟CALL_METHOD 操作码而不是LOAD_ATTR 和CALL_FUNCTION 操作码,但如果优化不适用,则回退到后两者的行为。
【讨论】: