Weak References in python

后端 未结 4 2135
醉梦人生
醉梦人生 2021-01-30 10:37

I have been trying to understand how python weak reference lists/dictionaries work. I\'ve read the documentation for it, however I cannot figure out how they work, and what the

相关标签:
4条回答
  • 2021-01-30 10:52

    Here is the example comparing dict and WeakValueDictionary:

    class C: pass
    ci=C()
    print(ci)
    
    wvd = weakref.WeakValueDictionary({'key' : ci})
    print(dict(wvd), len(wvd)) #1
    del ci
    print(dict(wvd), len(wvd)) #0
    
    ci2=C()
    d=dict()
    d['key']=ci2
    print(d, len(d))
    del ci2
    print(d, len(d))
    

    And here is the output:

    <__main__.C object at 0x00000213775A1E10>
    {'key': <__main__.C object at 0x00000213775A1E10>} 1
    {} 0
    {'key': <__main__.C object at 0x0000021306B0E588>} 1
    {'key': <__main__.C object at 0x0000021306B0E588>} 1
    

    Note how in the first case once we del ci the actual object will be also removed from the dictionary wvd.

    In the case or regular Python dictionary dict class, we may try to remove the object but it will still be there as shown.


    Note: if we use del, we do not to call gc.collect() after that, since just del effectively removes the object.

    0 讨论(0)
  • 2021-01-30 10:53

    Theory

    The reference count usually works as such: each time you create a reference to an object, it is increased by one, and whenever you delete a reference, it is decreased by one.

    Weak references allow you to create references to an object that will not increase the reference count.

    The reference count is used by python's Garbage Collector when it runs: any object whose reference count is 0 will be garbage collected.

    You would use weak references for expensive objects, or to avoid circle references (although the garbage collector usually does it on its own).

    Usage

    Here's a working example demonstrating their usage:

    import weakref
    import gc
    
    class MyObject(object):
        def my_method(self):
            print 'my_method was called!'
    
    obj = MyObject()
    r = weakref.ref(obj)
    
    gc.collect()
    assert r() is obj #r() allows you to access the object referenced: it's there.
    
    obj = 1 #Let's change what obj references to
    gc.collect()
    assert r() is None #There is no object left: it was gc'ed.
    
    0 讨论(0)
  • 2021-01-30 10:57

    Just want to point out that weakref.ref does not work for built-in list because there is no __weakref__ in the __slots__ of list. For example, the following code defines a list container that supports weakref.

    import weakref
    
    class weaklist(list):
        __slots__ = ('__weakref__',)
    
    l = weaklist()
    r = weakref.ref(l)
    
    0 讨论(0)
  • 2021-01-30 10:59

    The point is that they allow references to be retained to objects without preventing them from being garbage collected.

    The two main reasons why you would want this are where you do your own periodic resource management, e.g. closing files, but because the time between such passes may be long, the garbage collector may do it for you; or where you create an object, and it may be relatively expensive to track down where it is in the programme, but you still want to deal with instances that actually exist.

    The second case is probably the more common - it is appropriate when you are holding e.g. a list of objects to notify, and you don't want the notification system to prevent garbage collection.

    0 讨论(0)
提交回复
热议问题