在这里面被提到了. 今天我来说3个他没有提到的[__dir__, __slots__, __weakref__], 再强调下他提到的2个[__missing__, __contains__]
__dir__ -> 看个小例子就知道了
In [1]:classT(object):
...: pass
...:
In [2]: t = T()
In [3]: t.
啥也没有...
In [4]:classT2(object):
...: def__dir__(self):
...: return['a','b']
...:
In [5]: t = T2()
In [6]: t.
t.a t.b
In [7]: dir(t)
Out[7]: ['a','b']
看出来了把, 不解释, 但是这个__dir__是相对于类的实例有效果的.
__slots__
这个在我初学python的时候就被模糊了, 原来的理解是它的出现替代了__dict__,也就是说你只能给__slots__
代码例子(我对细节做注释):
# coding=utf-8
importsys
fromitertoolsimportstarmap, product
classSlotTest(object):
# __slots__ = ['x', 'y', 'z'] 主要对比去掉这句和包含这句程序内存占用
def__init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def__str__(self):
return"{} {} {}".format(self.x, self.y, self.z)
p = product(range(10000), range(20), [4])# 创建0-1000 & 0-20 & 4 的笛卡尔积
a = list(starmap(SlotTest, p)) # 相当于对每个SlotTest实例化,实例化的格式是p的长度
printa[0]
sys.stdin.read(1)
结果对比:
$pmap-x `ps -ef|grep test_slot.py|grep -v grep|awk'{print $2}'`|grep total# 未使用__slots__
total kB 103496 76480 73728
$pmap-x `ps -ef|grep test_slot.py|grep -v grep|awk'{print $2}'`|grep total# 使用了__slots__
total kB 49960 22888 20136
结果很明显,内存占用减少了很多…
__weakref__ 弱引用
首先先说下 weakref : 弱引用,与强引用相对,是指不能确保其引用的对象不会被垃圾回收器回收的引用。一个对象若只被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被回收.
在Python中,当一个对象的引用数目为0的时候,才会被从内存中回收. 但是被循环引用呢?
In [1]:importweakref
In [2]:importgc
In [3]:classObj(object):
...: defa(self):
...: return1
...:
In [4]: obj = Obj()
In [5]: s = obj
In [6]: gc.collect()# 不可达引用对象的数量
Out[6]:3
In [7]:printsisobj
True
In [8]: obj =1# 最初的被引用的对象改变了.
In [9]: gc.collect()
Out[9]:0
In [10]: sisNone# s还是指向了Obj 引用计数为1
Out[10]:False
In [11]: s
Out[11]: <__main__.Obj at0x2b36510>
----华丽的分割一下
In [12]: obj = Obj()
In [13]: r = weakref.ref(obj)# 让obj变成那个弱引用
In [14]: gc.collect()
Out[14]:211
In [15]: r()isobj
True
In [16]: obj =1
In [17]: gc.collect()
Out[17]:0
In [18]: r()isNone# 弱引用计数器没有增加,所以当obj不在引用Obj的时候,Obj对象就被释放了
Out[18]:True
好吧, 我的总结是弱引用是个好东西, 但是加了__slots__就不支持弱引用了. 所以需要__weakref__
In [9]: class T3(object):
...: __slots__ = []
...:
In [10]: class T4(object):
....: __slots__ = '__weakref__' # 这样就支持了weakref
....:
In [11]: import weakref
In [12]: t3 = T3()
In [13]: t4 = T4()
In [14]: weakref.ref(t3)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
in ()
----> 1 weakref.ref(t3)
TypeError: cannot create weak reference to 'T3' object
In [15]: weakref.ref(t4)
Out[15]:
__contains__ 判断某值 in/not in 实例
In [1]:classNewList(object):
...: def__init(self, values):
...: self.values = values
...: def__contains__(self, value):
...: returnvalueinself.values
...:
In [2]: l = NewList([1,2,3,4])
In [3]:4inl
Out[3]:True
In [4]:10inl
Out[4]:False
__missing__
最初看这个特殊方法是看python标准库的源码的时候(collections#L421):
classCounter(dict):
...
def__missing__(self, key):
'The count of elements not in the Counter is zero.'
# Needed so that self[missing_item] does not raise KeyError
return0
什么意思呢?
In [6]: c = collections.Counter({'a':1})
In [7]: c['b']# 没有键的count设置默认值0
Out[7]:0
很多人可能看过这个(关于defaultdict的ppt)[ http://discorporate.us/jek/talks/defaultdict/ ]. 内容就不说了, 讲的非常好.