Automatically delete class instance when one of its attributes becomes dead

后端 未结 2 379
既然无缘
既然无缘 2021-01-20 06:10

Set Up

Say I have a Snit:

class Snit(): pass

And a Snot, which contains weak references to up to, say,

2条回答
  •  再見小時候
    2021-01-20 06:46

    Nothing is truly automatic. You'll need to either have a function that you run manually to check for dead Snits, or have a function that is part of Snot that is called whenever anything interesting happens to a Snot to check for, and remove, dead Snits.

    For example:

    class Snot:
        ...
        def __repr__(self):
            # check for and remove any dead Snits
            self._remove_dead_snits()
            return ...
        def _remove_dead_snits(self):
            if self.s1() is None:
                 self.s1 = None
            ... # and so on and so forth
    

    The fun part is adding that call to _remove_dead_snits for every interesting interaction with a Snot -- such as __getitem__, __iter__, and whatever else you may do with it.


    Actually, thinking a bit more about this, if you only have the four possible Snits per each Snot you could use a SnitRef descriptor -- here's the code, with some changes to your original:

    import weakref
    
    class Snit(object):
        def __init__(self, value):
            self.value = value  # just for testing
        def __repr__(self):
            return 'Snit(%r)' % self.value
    
    class SnitRef(object):   # 'object' not needed in Python 3
        def __get__(self, inst, cls=None):
            if inst is None:
                return self
            return self.ref()  # either None or the obj
        def __set__(self, inst, obj):
            self.ref = weakref.ref(obj)
    
    
    class Snot(object):
        s0 = SnitRef()
        s1 = SnitRef()
        s2 = SnitRef()
        s3 = SnitRef()
        def __init__(self,s0=None,s1=None,s2=None,s3=None):
            self.s0 = s0
            self.s1 = s1
            self.s2 = s2
            self.s3 = s3
    
    snits = [Snit(0), Snit(1), Snit(2), Snit(3)]
    print snits
    snot = Snot(*snits)
    print(snot.s2)
    snits.pop(2)
    print snits
    print(snot.s2)
    

    and when run:

    [Snit(0), Snit(1), Snit(2), Snit(3)]
    Snit(2)
    [Snit(0), Snit(1), Snit(3)]
    None
    

提交回复
热议问题