Reputation: 14875
I have a class called Door
and a class called Window
. It's a child class to a class named Furniture
. My program reads excel files, loops over it 2 times, first time reading / writing everything about doors , the second time about windows. Simplified, I have the following code:
for gathering_inf in ('door', 'window'):
for row in file:
if gathering_inf == 'door' and currently reading door line:
furniture = Door(width, height, description)
if gatherig_inf == 'window' and currently reading window line:
furniture = Window(width, height, description)
# Now do something with the furniture object ..
The weird think that happens is, if I for example (as shown above) print the object furniture
, I get their location and, some of the objects' location in memory is the same, even though they are two different instances width different attributes. For example:
<__main__.Door object at 0x03BFE810>
<__main__.Door object at 0x03BFE890>
<__main__.Door object at 0x03BFE810>
<__main__.Door object at 0x03BFE890>
<__main__.Door object at 0x03BFE8B0>
<__main__.Door object at 0x03BFE8D0>
<__main__.Door object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE8D0>
<__main__.Window object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE890>
<__main__.Window object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE890>
<__main__.Window object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE890>
<__main__.Window object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE890>
Could someone explain to me why python behaves this way?
Upvotes: 2
Views: 231
Reputation: 9805
ThiefMaster pretty much nailed it: It's the way that the Python Virtual Machine works.
What you are observing is the specifics of the CPython implemetaion of the Reference counting Garbage collector. CPython in your case is garbage collecting the Door
object, and then creating a new Window
object, and then reuses the (now garbage collected) Door
object's location, storing the Window
object there.
It is in fact common to see CPython reuse addresses of objects that were previously garbage collected. For instance, running ThiefMaster's code on my computer I got slightly different (rotational) results:
At this point it is important to note that this behaviour is CPython
specific. For instance, Enthought's Python Distribution doesn't seem to produce similar results, however I do not know if this inconsistency is a matter of implementation difference:
Upvotes: 1
Reputation: 318518
That's because of the reference-counting garbage collector. As soon as a new object is assigned to furniture
the GC will delete the object and thus its memory location can be re-used by a new object.
Here's a small demo showing this behaviour. Note that because of the way the Python REPL works (it keeps a reference to the last result in _
) the addresses will alternate.
>>> foo = object(); foo
<object object at 0x7fd74cd390a0>
>>> foo = object(); foo
<object object at 0x7fd74cd390b0>
>>> foo = object(); foo
<object object at 0x7fd74cd390a0>
>>> foo = object(); foo
<object object at 0x7fd74cd390b0>
>>> foo = object(); foo
<object object at 0x7fd74cd390a0>
Upvotes: 4