在回答最近的问题时,我重复了我的假设,即使用的一个原因@staticmethod
是为了节省内存,因为静态方法只被实例化一次。这个断言可以在网上很容易找到(例如here https://newbedev.com/what-is-the-advantage-of-using-static-methods-in-python)而且我不知道我第一次遇到它是在哪里。
我的推理基于两个假设,其中一个是错误的: python在实例化一个类时实例化了所有方法(事实并非如此,稍加思考就会发现,哎呀)和b。静态方法没有在访问时实例化,而是直接调用。因此我认为这段代码:
import asyncio
class Test:
async def meth1():
await asyncio.sleep(10)
return 78
t1= Test()
t2 = Test()
loop = asyncio.get_event_loop
loop.create_task(t1)
loop.create_task(t2)
def main():
for _ in range(10):
await asyncio.sleep(2)
loop.run(main())
比我这样定义类会使用更多的内存:
class Test:
@staticmethod
async def meth1():
await asyncio.sleep(10)
return 78
是这样吗?静态方法会在访问时实例化吗?做类方法在访问时实例化?我知道t1.meth1 is t2.meth1
将返回True
在第二种情况下和False
在第一个中,但这是因为 python 正在实例化meth1
第一次然后第二次查找它,或者因为在这两种情况下它只是查找它,或者因为在这两种情况下它都会获得静态方法的副本,该副本在某种程度上是相同的(我认为不是这样?)id
静态方法的 似乎没有改变:但我不确定我对它的访问正在做什么。
如果是这样的话,现实世界有理由关心吗?我在 micropython 代码中看到了大量的静态方法,其中异步代码中同时存在多个实例。我以为这是为了节省内存,但我怀疑我错了。我很想知道 micropython 和 Cpython 实现之间是否有任何区别。
Edit我的想法是正确的t1.meth1()
and t2.meth1()
将绑定该方法twice首先并且once在第二?
方法不会被“实例化”,它们会被绑定——这是“它们的self
/cls
参数已填充”,类似partial参数绑定 https://docs.python.org/3/library/functools.html#functools.partial。整个点staticmethod
是没有self
/cls
参数,因此不需要绑定。
事实上,获取一个staticmethod
什么都不做——它只是返回函数不变:
>>> class Test:
... @staticmethod
... async def meth1():
... await asyncio.sleep(10)
... return 78
...
>>> Test.meth1
<function __main__.Test.meth1()>
由于方法是按需绑定的,因此它们通常不以绑定形式存在。因此,仅仅拥有方法就不需要支付内存成本,而无需支付任何内存成本。staticmethod
来弥补。自从staticmethod
是查找过程中的一个实际层 - 即使它什么都不做 - 无论哪种方式(不)使用都不会带来性能增益staticmethod
.
In [40]: class Test:
...: @staticmethod
...: def s_method():
...: pass
...: def i_method(self):
...: pass
...:
In [41]: %timeit Test.s_method
42.1 ns ± 0.576 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [42]: %timeit Test.i_method
40.9 ns ± 0.202 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
请注意,这些时间可能会因实施和测试设置而略有不同。结论是,这两种方法的速度相当快,并且性能与选择其中一种方法无关。
¹staticmethod
作为描述符 https://docs.python.org/3/reference/datamodel.html#object.__get__每次查找方法时都会运行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)