Python中的weakref的简单用法示例

目录

一、概念

二、解决问题

三、代码及解释

四、结论


一、概念

对一个对象的弱引用(weak reference)。相对于通常的引用来说,如果一个对象有一个常规的引用,它是不会被垃圾收集器销毁的,但是如果一个对象只剩下一个弱引用,那么它可能被垃圾收集器收回


二、解决问题

父亲节点的指针指向孩子节点,孩子节点又指向父亲节点,这构成了循环引用(circuclar reference),所以每个对象的引用计数(reference count)都不可能变成 0


三、代码及解释

1.use_weakA类中parent方法,决定self._parent被赋值为parent对象还是parent对象的弱引用

2.sys.getrefcount(parent):返回parent对象引用计数

3.weakref.ref(a):返回a弱引用(代码这里对child对象传入了parent对象

import weakref
import sys


class A:
    def __init__(self, data: str, use_weakref=None):
        """
        :param data: string
        :param use_weakref: flag for using weak reference
        """
        self.data = data
        self.use_weakref = use_weakref
        self.children = []

    def __repr__(self):
        """
        :return: print A object content
        """
        return '{}'.format(self.data)

    def __del__(self):
        """
        :return: delete massage
        """
        print('{}.__del__'.format(self.data))

    @property
    def parent(self):
        return self._parent

    @parent.setter
    def parent(self, a):
        """
        :param a: parent object
        :return: self._parent
        """
        if self.use_weakref:
            self._parent = weakref.ref(a)
        else:
            self._parent = a

    def add_child(self, child):
        """
        :param child: child object belongs to A class
        :return: self.children = [child]

        child's parent is parent self.
        """
        self.children.append(child)
        child.parent = self


if __name__ == '__main__':

    use_weakref = True  # True or False, determine if `weakref.ref(parent)` or just `parent`

    parent = A('parent', use_weakref)
    # print reference count of `parent`
    print(sys.getrefcount(parent))  # 2

    child = A('child', use_weakref)

    parent.add_child(child)  # Add child
    # print reference count of parent,
    # if `weakref.ref(parent)` in child,
    # the reference count will not be changed;
    # else `parent` in child,
    # the reference count will add 1.
    print(sys.getrefcount(parent))   # 2(not changed) or 3

    print(child.parent)

    del parent  # delete parent object
    # (1)if not use weak reference,
    #    `print(child.parent)-->parent` although `child.__del__` and `parent.__del__` has been printed.
    # (2)if use weak reference,
    #    `print(child.parent)-->,
    #    so weak reference is able to solve the circular reference when `garbage collection` happened.
    print(child.parent)


结果:

(1)如果use_weakrefTrue,则parent对象引用计数不变(为2),可成功删除parent,避免循环引用(可以看到引用从to 'A' 变成了dead

2
2

parent.__del__
 # `print(child.parent)` after `del parent`,delete parent object sucess!
child.__del__

(2)如果use_weakrefFalse,则parent对象引用计数加1(由2变为3),不能成功删除parent,循环引用仍旧存在

2
3
parent
parent    # `print(child.parent)` after `del parent`,delete parent object failed!
child.__del__
parent.__del__


四、结论

由此可见, 通过weakref来解决循环引用,即如果一个对象只剩下一个弱引用,那么它是可以被垃圾回收的

你可能感兴趣的:(Python,Object-Oriented,Programming,Python,面向对象,弱引用)