我有几个实例方法在其中使用了self
,但只有少数几个地方需要这样做。
我可以直接将这些对象传递给这些方法,并使它们成为staticmethod
。这会消耗更少的内存吗?
我有几个实例方法在其中使用了self
,但只有少数几个地方需要这样做。
我可以直接将这些对象传递给这些方法,并使它们成为staticmethod
。这会消耗更少的内存吗?
您在这里进行微观优化,但没有任何好处。
是的,常规方法涉及创建一个新的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上,在其他操作系统上字节数可能略有不同),但通常你不会保留绑定方法(你会使用instance.method()
,这样会创建方法对象,然后在调用之后将其丢弃)。
因此,除非你需要存储大量的绑定方法,否则这不足以证明通过手动在代码中传递实例使代码难以阅读。
* 注意,从Python 3.7开始,对于常见情况,Python甚至不再创建方法对象。请参阅3.7 What's New 说明书 中的 优化 部分:
由于字节码更改避免创建绑定方法实例,因此方法调用现在快了多达20%。
这适用于<expr>.attribute_name(...)
调用序列,即在同一整体表达式中直接跟随属性名称查找和调用,并且仅使用位置参数。生成特殊的字节码以验证attribute_name
是否解析为类上的方法名称,然后直接使用<expr>
之前的结果调用底层函数。 Python使用LOAD_METHOD
后跟CALL_METHOD
操作码,而不是LOAD_ATTR
和CALL_FUNCTION
操作码,但如果优化不适用,则回退到后两者的行为。