Reputation: 363
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...
Upvotes: 3
Views: 63
Reputation: 155418
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:
+
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 +=
.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
Upvotes: 3
Reputation: 1172
The del
keyword deletes a reference (or a name), not the object itself. Since you are using del
from inside a function, you are deleting that reference only within the function. That's why you're still able to access army2 even after you add army1+army2.
Python has garbage collection built-in, so I wouldn't worry about manually deleting variables, you'll most likely actually just end up slowing things down.
Upvotes: 1
Reputation: 24231
del other
will only make the 'other' name stop to exist and refer to your second army. That's all: just this name disappears, as it would have disappeared anyway once you exit this method.
The army2
object will only cease to exist once all the names referencing it will have been deleted and it gets garbage collected. That's not something you could do in your method.
Just let this second army get forgotten...
Upvotes: 1