0

my question is about class design and my current approach is inspired by this question/answer. Starting from there, I create multiple instances of the class Foobar which are collected and can be accessed via the class Foobar_Collection. Additionaly, the class Foo should have some method which is occasionally called for all instances. Now, conditional on the outcome of the method, is there a way to instantly delete an instance?

class Foobar_Collection(dict):
    def __init__(self, *arg, **kw):
        super(Foobar_Collection, self).__init__(*arg,**kw)
    def foobar(self,*arg,**kw):
        foo = Foo(*arg,**kw)
        self[foo.name] = foo
        return ins

class Foo(object):
    def __init__(self,name,something):
        self.name = name
        self.something = something
    # just some toy example method    
    def myMethod(self,x):
        if x < 0:
            #delete self
        else:
            print(x)

EDIT

Here is what I have in mind so far, but this is not "instantly" and it's "outside".

fc_collection = Foobar_Collection()
fc_collection.foobar( 'first', 42 )
fc_collection.foobar( 'second', 77 ) 

for name in fc_collection:
    # x will actually be a class attribute, for simplicity:
    if x<0:
        del fc_collection[name]
    else
        print(x)    
Community
  • 1
  • 1
Tim
  • 125
  • 3
  • 12
  • Remove Foo from the collection, by sure there are no other refs to it and then run gc.collect(), see https://docs.python.org/3/library/gc.html, also see http://stackoverflow.com/questions/6772481/how-to-force-deletion-of-a-python-object. – Jacques de Hooge Jan 23 '17 at 19:28
  • What is `ins` in `Foobar_collection.foobar`? – Patrick Haugh Jan 23 '17 at 19:30
  • I understand that I could do `del fb_collection[name]`, however, I wonder wether this could be achieved inside `myMethod`? Otherwise, could you please show me an example of what you mean? – Tim Jan 23 '17 at 19:32
  • @Patrick Haugh, sry that should be `foo`. – Tim Jan 23 '17 at 19:33
  • @Tim there is likely no non-hacky way to achieve this. Python uses reference counting. Maintain your references in order, and delete. No need to call `gc.collect()`. – juanpa.arrivillaga Jan 23 '17 at 19:34
  • Deleting self does not do what you want to achieve, it just removes self from the namespace: [See here](http://stackoverflow.com/a/293447/7384097) – UpSampler Jan 23 '17 at 19:35
  • 2
    You'll want to take care of this in `Foobar_Collection`. In `Foo.myMethod` you can set some property of `Foo`, `Foo.check` to `True` if it should get removed. Then you can recalculate the membership of `Foobar_collection` based on the `Foo.check` values. Don't worry about calling the garbage collector manually or anything, just remove all the references you're keeping and it will happen automatically. – Patrick Haugh Jan 23 '17 at 19:37
  • @ Patrick Haugh, thx for the hint. Would you be so kind and give a minimal example? I will appreciate this a lot. I also updated my question a bit. – Tim Jan 23 '17 at 19:44

1 Answers1

0

Usually when you have an object kill itself, you know your design is wrong. This is the case here.

You have Foobar responsible for adding Foos to the collection, but you want Foo to be responsible for removing itself from the collection.

Either Foobar manages the collection or Foo manages the collection. That way only one of them is aware, for instance, of the nature of the collection. In your case both classes need to know the collection is a dictionary whose key is foo.name .

Once you figure out who handles the collection, you'll see Foos no longer need to delete themselves, and the ordinary Python garbage collector will work just fine.

zmbq
  • 38,013
  • 14
  • 101
  • 171
  • I can imagine to include a method in `Foobar_Collection` which, upon being called, checks for some condition and deletes the respective instance. Could such be automated? – Tim Jan 23 '17 at 20:05
  • I would make Foo aware of Foobar_Collection and receive it in its __init__ method. Foo can then call "i_am_not_worthy" on Foobar_Collection when the time comes, and Foobar_Collection can then remove the instance from the collection. – zmbq Jan 23 '17 at 20:07
  • Could you give a minimal working example of your first statement please (make Foo aware of Foobar_Collection)? – Tim Jan 23 '17 at 20:11
  • Tim: I disagree about making `Foobar` aware of `Foobar_Collection` (assuming that's what you meant—there is nothing named `Foo` in your code). The couples the two classes together and might get in the way of `Foobar` instances being in other kinds of collections or subclassing it later. Think generically. Give `Foobar` instances some kind of attribute, property, or method that would let other objects, such as `Foobar_Collection` instance or even just a standalone function, query it to see if it's a candidate for deletion (or some other operation). – martineau Jan 23 '17 at 21:07