Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

delete instance after addition

Tags:

python

oop

I'm trying to learn OOP with python. I'm wondering how I can create armies and when I merge them, delete the one that merged with the one specified.

class Army:
    def __init__(self, spear, sword, archer):
        self.composition = {'spear': spear, 'sword': sword, 'archer': archer}

    def __add__(self, other):
        for item in other.composition:
            self.composition[item] += other.composition[item]
        del other

Then typing this in the console:

army1 = Army(10, 20, 30)
army2 = Army(30, 5, 0)
army1+army2

doesn't delete army2. However, if I type del army2, it does delete the instance...

like image 624
mooder Avatar asked Dec 05 '25 03:12

mooder


1 Answers

The reason this doesn't work is that del on a raw name only unbinds the object from that specific name. If the object is referenced elsewhere, in this case by army2 in the caller, then the object continues to exist; del has no effect beyond denying access under the specific name del-ed.

If you must have this behavior, I recommend two things:

  1. Don't overload an operator for this behavior; + is not expected to affect either operand, it's supposed to produce a brand new object with the sum/concatenation of both. While += is allowed to modify the left hand operand, it shouldn't be modifying the right hand operand. When overloading operators, the usual rule of thumb is "Don't", followed by "Okay, but only if it obeys the expected semantics of that operator", and this case definitely doesn't match the expected semantics of either + or +=.
  2. Now that we've settled on using a method, you can remove the troops from the other army, by removing the contents of the other army. For example:

    class Army:
        def __init__(self, spear, sword, archer):
            self.composition = {'spear': spear, 'sword': sword, 'archer': archer}
    
        def absorb_army(self, other):  # or transfer_troops or whatever
            '''Removes all the troops from other, combining them with the troops of self'''
            for item in other.composition:
                self.composition[item] += other.composition[item]
            other.composition.clear()  # Leaves other.composition empty
    
    army1 = Army(10, 20, 30)
    army2 = Army(30, 5, 0)
    army1.absorb_army(army2)
    # army2 still exists, but all the troops in it are gone, moved to army1
    

Note that the absorb_army I wrote might violate other constraints of your class (because all elements of your class may be expected to have composition include 'spear', 'sword' and 'archer'. If that's an issue, don't clear it, just reassign all the keys to zero, e.g.:

        def absorb_army(self, other):
            for item in other.composition:
                self.composition[item] += other.composition[item]
                other.composition[item] = 0  # Zero after adding to self
like image 111
ShadowRanger Avatar answered Dec 07 '25 15:12

ShadowRanger