我有几个实例方法在其中使用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 新增功能说明中的优化部分:
由于字节码更改避免了创建绑定方法实例,方法调用现在提高了 20%。
这适用于<expr>.attribute_name(...)
调用序列,因此,如果仅使用位置参数,则在同一整体表达式中,属性名称查找后直接跟一个调用。生成特殊的字节码,用于验证attribute_name
解析为类上的方法名称,然后直接调用基础函数,并附加<expr>
的结果。Python 使用LOAD_METHOD
后跟CALL_METHOD
操作码而不是LOAD_ATTR
和CALL_FUNCTION
操作码,但如果优化不适用,则会回退到后两者的行为。