python 静态方法是否比实例方法消耗更少的内存
Does python static method consume less memory than instance method
我有几个在其中使用 self
的实例方法,但只在几个地方。
我可以直接将对象传递给这些方法并使它们成为 staticmethod
。这会占用更少的内存吗?
您在这里进行微优化没有任何好处。
是的,常规方法涉及一个新的 method
对象,该对象是为处理函数和实例之间的绑定而创建的,但这只是一点点内存(2 个指针加上一些 Python 元数据) 仅在调用期间或存储绑定方法时使用 *。 staticmethod
对象不会创建新的方法对象,但是 抵消了 staticmethod
对象:[=26 所需的大约相同内存量=]
>>> 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 上,在另一个 OS 上字节数可能略有不同),但您不需要通常 保留 绑定方法(您会使用 instance.method()
,它创建方法对象,然后在调用后再次丢弃它)。
因此,除非您存储大量绑定方法,否则这不会产生足够的差异来证明通过在任何地方手动传递实例来使您的代码不可读。
* 请注意,从 Python 3.7 开始,对于常见情况 Python 甚至不再创建方法对象。见 Optimisations section of the 3.7 What's New notes:
Method calls are now up to 20% faster due to the bytecode changes which avoid creating bound method instances.
这适用于 <expr>.attribute_name(...)
调用序列,因此在同一整体表达式中,属性名称查找后直接跟一个调用,前提是仅使用位置参数。生成的特殊字节码验证 attribute_name
解析为 class 上的方法名称,然后直接调用底层函数,并在前面加上 <expr>
的结果。 Python 使用 LOAD_METHOD
followed by CALL_METHOD
opcodes instead of LOAD_ATTR
and CALL_FUNCTION
操作码,但如果优化不适用,则回退到后两者的行为。
我有几个在其中使用 self
的实例方法,但只在几个地方。
我可以直接将对象传递给这些方法并使它们成为 staticmethod
。这会占用更少的内存吗?
您在这里进行微优化没有任何好处。
是的,常规方法涉及一个新的 method
对象,该对象是为处理函数和实例之间的绑定而创建的,但这只是一点点内存(2 个指针加上一些 Python 元数据) 仅在调用期间或存储绑定方法时使用 *。 staticmethod
对象不会创建新的方法对象,但是 抵消了 staticmethod
对象:[=26 所需的大约相同内存量=]
>>> 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 上,在另一个 OS 上字节数可能略有不同),但您不需要通常 保留 绑定方法(您会使用 instance.method()
,它创建方法对象,然后在调用后再次丢弃它)。
因此,除非您存储大量绑定方法,否则这不会产生足够的差异来证明通过在任何地方手动传递实例来使您的代码不可读。
* 请注意,从 Python 3.7 开始,对于常见情况 Python 甚至不再创建方法对象。见 Optimisations section of the 3.7 What's New notes:
Method calls are now up to 20% faster due to the bytecode changes which avoid creating bound method instances.
这适用于 <expr>.attribute_name(...)
调用序列,因此在同一整体表达式中,属性名称查找后直接跟一个调用,前提是仅使用位置参数。生成的特殊字节码验证 attribute_name
解析为 class 上的方法名称,然后直接调用底层函数,并在前面加上 <expr>
的结果。 Python 使用 LOAD_METHOD
followed by CALL_METHOD
opcodes instead of LOAD_ATTR
and CALL_FUNCTION
操作码,但如果优化不适用,则回退到后两者的行为。