python - @staticmethod 是否在 CPython 或 Micropython 中保存任何 ram?
问题描述
在回答最近的一个问题时,我重复了我的假设,即使用的一个原因@staticmethod
是为了节省 ram,因为静态方法只实例化一次。这个断言可以很容易地在网上找到(例如这里),我不知道我第一次遇到它的地方。
我的推理基于两个假设,一个是错误的:那个python在实例化一个类时实例化了所有方法(事实并非如此,正如一点点的想法会表明,哎呀)和b。staticmethods 没有在访问时实例化,而是直接调用。因此我认为这段代码:
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
,但那是因为pythonmeth1
第一次实例化然后第二次查找它,或者因为在这两种情况下它只是查找它,或者因为在这两种情况下它都得到了静态方法的副本,它在某种程度上是相同的(我想不是吗?)id
静态方法的 似乎没有改变:但我不确定我对它的访问在做什么。
如果是这样,是否有任何现实世界的理由关心?我在 micropython 代码中看到了大量的静态方法,其中异步代码中同时存在多个实例。我以为这是为了节省内存,但我怀疑我错了。我很想知道这里的 micropython 和 Cpython 实现之间是否有任何区别。
编辑
我认为调用t1.meth1()
并将在第一个实例中t2.meth1()
绑定该方法两次,在第二个实例中绑定该方法是正确的?
解决方案
方法不会被“实例化”,它们会被绑定——这是“他们的self
/cls
参数被填充”的一个花哨的词,类似于partial
参数绑定。的全部要点staticmethod
是没有self
/cls
参数,因此不需要绑定。
事实上,获取 astaticmethod
根本没有任何作用——它只是返回未更改的函数:
>>> 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
用作每次查找方法时运行的描述符。
推荐阅读
- javascript - isset() 不适用于动态形式
- python - 需要在python的networkx库中改变节点的形状
- python - 替换捕获组中的多个字符
- debugging - 如何在 Visual Studio 2019 中安装 64 位 SSIS 运行时
- python - 如何使用循环打印这些哈希符号?
- javascript - Javascript 仅在我的 html 的一部分中工作,但在其他任何地方都没有
- python - 使用列表值获取字典键
- ajax - 如何显示控制器动作返回的数据
- simulation - 球体之间的滚动接触
- command-line - 终端不响应任何命令