Python中有很多以__开头的变量,这些变量是什么意思?这里是 [__dir__, __slots__, __weakref__, __missing__, __contains__]
__dir__
-> 看个小例子就知道了
In [1]: class T(object):
...: pass
...:
In [2]: t = T()
In [3]: t.<Tab>
啥也没有...
In [4]: class T2(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__的属性赋值。外部接口减少,安全。 .后来我读了这篇文章,用 Python 的插槽节省 9 GB 的 RAM。好久没做运维了。我无法对生产环境下结论。我还提到,当对象实例很多时,它可以帮助减少内存。有关详细信息,请参阅 https://www.safaribooksonline.com/library/view/python-cookbook-3rd/9781449357337/ch08s04.html。这是一个小实验(也在 Hacker News https://news.ycombinator.com/item ?id=6750187 上讨论过)
代码例子(我对细节做注释):
# coding=utf-8
import sys
from itertools import starmap, product
class SlotTest(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的长度
print a[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 中,只有当对象的引用次数为零时才从内存中回收。但是循环引用呢?
In [1]: import weakref
In [2]: import gc
In [3]: class Obj(object):
...: def a(self):
...: return 1
...:
In [4]: obj = Obj()
In [5]: s = obj
In [6]: gc.collect() # 不可达引用对象的数量
Out[6]: 3
In [7]: print s is obj
True
In [8]: obj = 1 # 最初的被引用的对象改变了.
In [9]: gc.collect()
Out[9]: 0
In [10]: s is None # s还是指向了Obj 引用计数为1
Out[10]: False
In [11]: s
Out[11]: <__main__.Obj at 0x2b36510>
----华丽的分割一下
In [12]: obj = Obj()
In [13]: r = weakref.ref(obj) # 让obj变成那个弱引用
In [14]: gc.collect()
Out[14]: 211
In [15]: r() is obj
True
In [16]: obj = 1
In [17]: gc.collect()
Out[17]: 0
In [18]: r() is None # 弱引用计数器没有增加,所以当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)
<ipython-input-14-bdb7ab7ac3bc> in <module>()
----> 1 weakref.ref(t3)
TypeError: cannot create weak reference to 'T3' object
In [15]: weakref.ref(t4)
Out[15]: <weakref at 0x2766f70; to 'T4' at 0x2586fd8>
__contains__ 判断某值 in/not in 实例
In [1]: class NewList(object):
...: def __init(self, values):
...: self.values = values
...: def __contains__(self, value):
...: return value in self.values
...:
In [2]: l = NewList([1, 2, 3, 4])
In [3]: 4 in l
Out[3]: True
In [4]: 10 in l
Out[4]: False
__missing__
第一次看这个特殊方法是在看python标准库(collections#L421)的源码的时候:
class Counter(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
return 0
什么意思呢?
In [6]: c = collections.Counter({'a':1})
In [7]: c['b'] # 没有键的count设置默认值0
Out[7]: 0
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ python如何关闭应用程序?10/02
- ♥ 如何使用python的str函数09/14
- ♥ python如何用函数删除空格10/19
- ♥ python如何读取yaml文件12/12
- ♥ 在 python 中使用日志记录的好处12/01
- ♥ 如何用python导入随机库?10/27
内容反馈