美文网首页
Fluent Python笔记--垃圾回收

Fluent Python笔记--垃圾回收

作者: MontyOak | 来源:发表于2018-01-21 21:18 被阅读22次

    在复制list时,默认是做了浅拷贝(shallow copy),也就是说复制了最外层垯容器,而内部元素则是原容器的引用。这么做在内部元素都是不可变类型的时候没有问题,但是在内部包含可变元素的时候会发生一些意想不到的情况:

    >>> l1 = [3, [66, 55, 44], (7, 8, 9)]
    >>> l2 = list(l1) 
    >>> l1.append(100) 
    >>> l1[1].remove(55) 
    >>> print('l1:', l1)
    l1: [3, [66, 44], (7, 8, 9), 100]
    >>> print('l2:', l2)
    l2: [3, [66, 44], (7, 8, 9)]
    >>> l2[1] += [33, 22] 
    >>> l2[2] += (10, 11) 
    >>> print('l1:', l1)
    l1: [3, [66, 44, 33, 22], (7, 8, 9), 100]
    >>> print('l2:', l2)
    l2: [3, [66, 44, 33, 22], (7, 8, 9, 10, 11)]
    

    所以,当容器中包含可变元素的时候,为了避免意想不到的情况发生,推荐使用深拷贝,即copy.deepcopy
    Python中的函数传参是共享传参(call by sharing),即函数形参获得实参中各个引用的副本。带来的副作用是函数内部的操作可能会影响到可变类型的实参。

    >>> def f(a, b):
    ... a += b
    ... return a
    ...
    >>> x = 1
    >>> y = 2
    >>> f(x, y)
    3
    >>> x, y 
    (1, 2)
    >>> a = [1, 2]
    >>> b = [3, 4]
    >>> f(a, b)
    [1, 2, 3, 4]
    >>> a, b 
    ([1, 2, 3, 4], [3, 4])
    >>> t = (10, 20)
    >>> u = (30, 40)
    >>> f(t, u)
    (10, 20, 30, 40)
    >>> t, u 
    ((10, 20), (30, 40))
    

    Python默认解释器CPython中,默认使用引用计数来做垃圾回收。每个对象维护一个变量,计算自己被引用的次数,当这个值归零之后,对象被销毁,执行__del__方法。对于有循环引用的对象,则使用分代垃圾回收算法。

    按照上面的说法,引用数归零之后对象被垃圾回收。有时需要引用对象而不想让它存活超过所需时间,比如缓存。
    这时候就需要引入弱引用的概念。

    >>> import weakref
    >>> a_set = {0, 1}
    >>> wref = weakref.ref(a_set) 
    >>> wref
    <weakref at 0x100637598; to 'set' at 0x100636748>
    >>> wref() 
    {0, 1}
    >>> a_set = {2, 3, 4} 
    >>> wref() 
    {0, 1}
    >>> wref() is None 
    False
    >>> wref() is None 
    True
    

    下面演示 WeakValueDictionary的用法:

    class Cheese:
        def __init__(self, kind):
            self.kind = kind
        def __repr__(self):
            return 'Cheese(%r)' % self.kind
    
    >>> import weakref
    >>> stock = weakref.WeakValueDictionary() 
    >>> catalog = [Cheese('Red Leicester'), Cheese('Tilsit'),
    ... Cheese('Brie'), Cheese('Parmesan')]
    ...
    >>> for cheese in catalog:
    ... stock[cheese.kind] = cheese 
    ...
    >>> sorted(stock.keys())
    ['Brie', 'Parmesan', 'Red Leicester', 'Tilsit'] 
    >>> del catalog
    >>> sorted(stock.keys())
    ['Parmesan'] 
    >>> del cheese
    >>> sorted(stock.keys())
    []
    

    相关文章

      网友评论

          本文标题:Fluent Python笔记--垃圾回收

          本文链接:https://www.haomeiwen.com/subject/xykqaxtx.html