Domanda

I am trying to figure out the best way to remove something, preferably without having to write in a lot of code.

In my project I am simulating chemical compounds - I have Element instances bonded to other Element instances via a Bond instance. In chemistry bonds often break, and I'd like to have a clean way to do that. My current method is something like as follows

# aBond is some Bond instance
#
# all Element instances have a 'bondList' of all bonds they are part of
# they also have a method 'removeBond(someBond)' that removes a given bond 
# from that bondList
element1.removeBond(aBond)
element2.removeBond(aBond)
del aBond

I want to do something like

aBond.breakBond()

class Bond():
    def breakBond(self):
        self.start.removeBond(self) # refers to the first part of the Bond 
        self.end.removeBond(self) # refers to the second part of the Bond 
        del self

Alternately, something like this would be fine

del aBond

class Bond():
    def __del__(self):
        self.start.removeBond(self) # refers to the first part of the Bond 
        self.end.removeBond(self) # refers to the second part of the Bond 
        del self

Is any one of these ways of doing it preferable to the others, or is there some other way of doing this that I'm overlooking?

È stato utile?

Soluzione

Python uses garbage collection to manager memory, which means you do not have to delete anything. This class is fine:

class Bond():
    def breakBond(self):
        self.start.removeBond(self)
        self.end.removeBond(self)

note that del does not delete anything from memory! It simply removes a reference to an object, but objects can have more than one reference:

>>> some_list = [1,2,3]
>>> b = some_list
>>> del b   # destroys the list?
>>> b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
>>> some_list   # list is still there!
[1, 2, 3]
>>> c = some_list
>>> del some_list
>>> c        # list is still there!
[1, 2, 3]
>>> del c

After the last del c the interpreter can deallocate the list. In CPython the deallocation will be done immediately (in this simple case), however in other implementation of the language the interpreter might not deallocate the list immediately.

Also note that __del__'s documentation cites this fact. Furthermore it is a really low-level method which you don't need 99.9% of the time, so it certainly isn't the right way to handle your situation.

Altri suggerimenti

The first way is pretty tedious and error-prone. The second is fine, but the del self in Bond.breakBond is completely and utterly pointless (more on this below). The third is hacky, unreliable, and in this specific case not working at all (due to the circular reference between Bond and Elements, __del__ is never invoked unless you upgrade to Python 3.4, but even then it remains hacky and unreliable).

del name only removes the local name, it does not call __del__ or otherwise affect the object. It has absolutely no effect on memory management, except possibly allowing earlier garbage collection if name was the last (reachable) reference.

You should do this:

aBond.breakBond()

class Bond():
    def breakBond(self):
        self.start.removeBond(self) # refers to the first part of the Bond 
        self.end.removeBond(self) # refers to the second part of the Bond 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top