为什么使用__slots__减慢这段代码?
我Usage of __slots__?读到,在使用Python __slots__
实际上可以节省时间。但是,当我试图找到使用datetime
所花的时间时,结果是相反的。为什么使用__slots__减慢这段代码?
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)
都给输出: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)
都给输出:0:00:00.000021
使用插槽实际所花的时间。为什么我们需要使用__slots__
呢?
- 你报的文章说使用插槽提供了更快的 属性访问 - 你测试的对象创建的时间,和 从来没有访问您的对象的属性。
- 测试单个操作不是统计意义 - 衡量的,比如100000次行动的时间。
__slots__
可以节省时间(取决于Python版本),但这通常不是您使用它的原因。它真正节省的是内存。而不是每个实例相当大的__dict__
。即使在现代PY3 64与密钥共享类型的字典,它仍然是一个关键的共享__dict__
所在班级有一个实例属性,对对象结构本身的56个字节的最高96个字节。
使用__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
这就是每实例超过100字节的节省;在Py2上(没有密钥共享词典),节省更多。
因此,并不是说__slots__
通常速度更快(通常非常相似),但是如果您制作数百万个实例,则每个实例节省100 + B可能会帮助您将代码保存在缓存中,RAM等中。 ,而不是耗尽内存并分出一半数据进行交换。
至于对方的回答笔记,你从来没有真正进入你的属性,所以你没有标杆槽接可言,这就是为什么你看到的没有什么区别的。使用ipython3
%%timeit
魔法,我发现反复加载给定实例的属性x
约15%的速度时,它的开槽(33.5 ns有__slots__
与39.2纳秒无),但这只是在明显的微基准;它在真正的代码中很少重要(实际的工作不仅仅是属性查找)。重要的是,将内存使用量减少2-3倍是更大的收益。
我注意,手动使用'datetime'这种方式不是用于定时码的推荐方法。有[用于计时代码片段的模块](https://docs.python.org/3/library/timeit.html)。 (正如答案中提到的)你必须多次重复短操作才能使任何事情接近有意义的结果。 –