Ayu*_*har 1 python performance time class slots
我读过《 __slots__用法》吗?__slots__在Python 中使用实际上可以节省时间。但是,当我尝试使用花费时间时datetime,结果却相反。
import datetime as t
class A():
def __init__(self,x,y):
self.x = x
self.y = y
t1 = t.datetime.now()
a = A(1,2)
t2 = t.datetime.now()
print(t2-t1)
Run Code Online (Sandbox Code Playgroud)
...给出了输出:0:00:00.000011
并使用插槽:
import datetime as t
class A():
__slots__ = 'x','y'
def __init__(self,x,y):
self.x = x
self.y = y
t1 = t.datetime.now()
a = A(1,2)
t2 = t.datetime.now()
print(t2-t1)
Run Code Online (Sandbox Code Playgroud)
...给出了输出: 0:00:00.000021
使用插槽实际上花费了更长的时间。为什么我们需要使用__slots__呢?
__slots__可以节省时间(取决于Python版本),但这通常不是您使用的时间。它真正节省的是内存。__dict__您可以将属性直接存储在支持该对象的C结构中,而不是为每个实例分配一个相当大的大小,并且类本身可以存储查找表的单个副本,该副本从名称映射到每个属性的结构偏移量。即使在具有键共享字典的现代Py3 x64上,键共享仍为96字节,__dict__其中该类具有单个实例属性,在对象结构本身的56个字节之上。
通过使用__slots__,可以消除指向__dict__和__weakref__属性的指针的16个字节,并__dict__完全消除。
为了在Py 3.5上进行比较:
>>> class Foo:
... def __init__(self, x): self.x = x
...
>>> sys.getsizeof(Foo(1)) + sys.getsizeof(Foo(1).__dict__)
152
>>> class Foo:
... __slots__ = 'x',
... def __init__(self, x): self.x = x
...
>>> sys.getsizeof(Foo(1)) # With __slots__, doesn't have __dict__ at all
48
Run Code Online (Sandbox Code Playgroud)
这样每个实例可以节省100多个字节。在Py2(无密钥共享字典)上,节省的费用更大。
因此,__slots__通常这并不是更快(通常非常相似),但是如果您要创建数百万个实例,则为每个实例节省100+ B可能有助于您将代码保存在缓存,RAM等中,而不是耗尽内存并分页出一半数据以进行交换。
如其他答案所述,您实际上从未访问过属性,因此根本就没有基准测试插槽访问权限,这就是为什么看不到任何区别的原因。使用ipython3 %%timeit魔术,我发现x重复加载给定实例的属性在插入时隙时大约快15%(有33.5 ns __slots__对比无对象39.2 ns),但这仅在微基准测试中很明显。在实际代码中(在实际工作中所做的不仅仅是属性查找而已)还很少。重要的是,将内存使用量减少2-3倍是更大的收益。