Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different class instances use same memory location

Tags:

python

I was playing around with the pickle library, when I noticed that sometimes, different class instances are at the same memory location.

Both of the below examples are showcasing said behaviour:

class DemoClass:
    def __init__(self):
        self.name = 'demoName'

#example 1
for i in range(3):
    print (DemoClass())

#example 2
[print(DemoClass()) for i in range(3)]

#Output for both example 1 and example 2
#Note that the memory locations are identical in the output
<__main__.DemoClass object at 0x00CEE610>
<__main__.DemoClass object at 0x00CEE610>
<__main__.DemoClass object at 0x00CEE610>

This was quite startling to me, so maybe you could explain why this occurs.

The way in which the program acts as I would expect it to is as follows.

demo = [DemoClass() for i in range(3)]
for i in demo:
    print (i)

#Output
<__main__.DemoClass object at 0x01F7E630>
<__main__.DemoClass object at 0x01F7ED30>
<__main__.DemoClass object at 0x01F7E670>
like image 464
Mario Geuenich Avatar asked Nov 09 '16 19:11

Mario Geuenich


People also ask

Is same objects occupy same memory location in memory?

The answer is No : If you create two objects using the new keyword, they will never point to the same memory location. This holds true for String objects as well. if you create two String objects using new , the two references to these objects will point to two different memory locations.

Where are class instances stored?

For instance and class variables, they are part of the object, hence, on the heap. While Objects are stored on heap. Class objects, including method code and static fields: heap.

How do you find the memory address of an instance of a class?

We can get an address using the id() function. id() function gives the address of the particular object.

Can you create multiple instances of a class?

A program may create many objects of the same class. Objects are also called instances, and they can be stored in either a named variable or in an array or collection. Client code is the code that uses these variables to call the methods and access the public properties of the object.


3 Answers

Your question concerns how Python allocates memory. tldr; Python uses a heap to store memory. When a resource is freed, it goes to the top of the heap.

Detailed Answer

Python has to allocate memory to create an instance of an object. For memory efficiency, the Python memory manager has a heap of memory locations available to give or reserve for the instantiation of objects. Using some of your examples, you can see how this works in practice.

Example #1

>>> for i in range(3):
...     print(DemoClass())
... 
<test.DemoClass instance at 0x288b248>
<test.DemoClass instance at 0x288b248>
<test.DemoClass instance at 0x288b248>

During the first iteration of the for loop, python uses the first available address in its current heap, namely <0x288b248>, to create an instance of DemoClass for the print call. Once the print command has finished, the memory address is freed and returns to the top of the heap. During the next iteration of the loop, python utilizes the first available memory address, which again is address <0x288b248>. Etc.

Example #2

>>> for j in [DemoClass() for i in range(3)]:
...     print(j)
... 
<test.DemoClass instance at 0x288bcf8>
<test.DemoClass instance at 0x288b290>
<test.DemoClass instance at 0x288b638>

Here python generates a list that it will then iterate through. The creation of the list requires that a new instance of DemoClass be created for each element. This will take the top three addresses off the heap. After the loop is done, the list is freed from memory and if we again make a call to print(DemoClass) we will find that the python is again reusing memory.

>>> print DemoClass()
<test.DemoClass instance at 0x288bcf8>

Example 3 (My Example of Alternating Memory Allocation)

>>> for i in range(4):
...     Demo = DemoClass()
...     print(Demo)
... 
<test.DemoClass instance at 0x288bcf8>
<test.DemoClass instance at 0x288b290>
<test.DemoClass instance at 0x288bcf8>
<test.DemoClass instance at 0x288b290>

In this example, each time Demo is instantiated as an instance of DemoClass, a segment of memory is assigned to Demo. However, the call to print(Demo) does not free the memory assigned to Demo. At the beginning of the next loop, a new segment of memory is allocated to Demo and then Demo is overwritten, at which point it's original memory address returns to the top of the heap. The memory address used for Demo then alternates between two memory addresses.

like image 192
Mark Hannel Avatar answered Nov 04 '22 17:11

Mark Hannel


In your first 2 examples, once the call to print has finished, the object no longer has a reference, and so can be re-used the next time that type of object is created.

In the second, all of the instances have references at the same time, and thus must be distinct.

I wouldn't rely on this behavior, though: for example, there might be other unreferenced instances of that object lying about.

like image 26
Scott Hunter Avatar answered Nov 04 '22 16:11

Scott Hunter


When an object doesn't exist any more, its location is available for reuse immediately.
Since Python objects are reference-counted, they disappear as soon as nothing refers to them.

If things worked the way you expect, you could run out of memory rather quickly.

like image 25
molbdnilo Avatar answered Nov 04 '22 15:11

molbdnilo