MarkLilyCC
MarkLilyCC

Reputation: 53

Why does the self in the class always have the previous data?

im new to python and today i had this problem:

say, i have this code incluing two classes named: slice and mat:


class slice():
    def __init__(self, var:int) -> None:
        self.__var = var
    @property
    def var(self):
        return self.__var

class mat():
    __slices = []
    def __init__(self,var:list) -> None:
        self.__var = var
        for i in var:
            self.__slices.append(slice(i))
    @property
    def val(self):
        return self.__var
    @property
    def slices(self):
        return self.__slices

ori_data = [
    [1,2,3,4],
    [5,6,7,8]
]

list_mat = []
for i in ori_data:
    list_mat.append(mat(i))
print(len(list_mat))
for i in list_mat:
    print(i.slices)

output:

2
[<__main__.slice object at 0x000002B20597E908>, <__main__.slice object at 0x000002B205957FC8>, <__main__.slice object at 0x000002B2059C7588>, <__main__.slice object at 0x000002B2059C76C8>, <__main__.slice object at 0x000002B2059C7508>, <__main__.slice object at 0x000002B2059D3708>, <__main__.slice object at 0x000002B2059D37C8>, <__main__.slice object at 0x000002B2059D3808>]
[<__main__.slice object at 0x000002B20597E908>, <__main__.slice object at 0x000002B205957FC8>, <__main__.slice object at 0x000002B2059C7588>, <__main__.slice object at 0x000002B2059C76C8>, <__main__.slice object at 0x000002B2059C7508>, <__main__.slice object at 0x000002B2059D3708>, <__main__.slice object at 0x000002B2059D37C8>, <__main__.slice object at 0x000002B2059D3808>]

I thought that: the list_mat would have 2 mat object(which is true by the output of print(len(list_mat)))

And i thought every mat object in list_mat would have 4 slice objects and the var for each slice obj would be 1 2 3 4 and 5 6 7 8 for each mat obj.

But when it came to the actual mat object in the list_mat,every mat have 8 slice objects and they had the exactly same 8 slice objects in the memory.

When i debugged, i found that when i created the second mat object, in the __init__, the self already had previous value(which were the slices created for the first mat). So that when i passed the second list 5 6 7 8 for the constructor, it would just add another 4 slice objects for the second mat which gave me the result of 8 slice objects.

Another thing is when the second mat was created, the __slice in the first mat changed into the __slice in the second mat! Actually when i checked the __init__ function when debugged, i found that the address of the second mat's self object, it was the address of the first mat object which had beed created already.

There must be some deepcopy stuff i have missed.

So to sum:

1: during a for loop, the self obj for the mat class always has the previous data left by the creation of the first mat obj

2: during a for loop, how can i deepcopy and created a whole new obj with everything created new in the memory

Any advice would help!

let me know if you don't understand my question!

Wishes!

Upvotes: 0

Views: 86

Answers (2)

sahasrara62
sahasrara62

Reputation: 11238

This is happening because class variable __slices = [] is keep getting updated and keep shared among all class instance. so in last iteration when last element is added then it get reference to all other object (class instance) appended in the list and show this behavior.

More Information, Python class variable are for attributes and methods shared by all instances of the class.

Upvotes: 1

Cargo23
Cargo23

Reputation: 3189

@jasonharper had it right.....

class mat():
    __slices = []

This code creates a CLASS LEVEL variable which is shared by all instances of the class. This is useful for example, if you wanted to have a object_count variable which you increment during object creation and decrement during destruction. But, in your case, you want each mat object to have its own __slices, so you want to define that variable within __init__():

    def __init__(self,var:list) -> None:
        self.__var = var
        self.__slices = []

Upvotes: 1

Related Questions