don't understand instanse creation

Christopher Subich spam.csubich+block at block.subich.spam.com
Tue Aug 9 16:30:13 CEST 2005


Maksim Kasimov wrote:

 >
 > Hello,
 >
 > i have a class, such as below.
 > when i try to make instances of the class,
 > fields __data1 and __data2 gets different values: __data1 behaves 
like private field, __data2 - like static
 > which is the thing i've missed?


Firstly, you get interesting behaviour of data1 and data2 because 
they're defined as mutable objects in the class sitself.  All instances 
of that class then share the same binding to the list, so appending to 
it in one instance will show up in other instances.

(Incidentally, be sure what you really want is name-mangled private 
variables, it's fairly uncommon for instance variables and methods to be 
private in Python code).

Your second issue is why data1 behaves differently.  This line:

 >         self.__data1 = self.__data2[:]


is the culprit.  Here, you assing __data1 to a *new* list, generated by 
copying __data2 (the : slice -- slices create a shallow copy, not a 
reference, of lists).  This rebinds the name __data1 to a new object, so 
the __data1 in the class definition is never modified like __data2 (with 
the .append).  You can demonstrate this by looking at the 'address' of 
the lists.  Modify the constructor thusly:

class my:

     __data1 = []
     __data2 = []

     def __init__(self):

         print "__data1: ", self.__data1, object.__repr__(self.__data1)
         print "__data2: ", self.__data2, object.__repr__(self.__data1)

         for i in time.localtime():
             self.__data2.append(i)
         self.__data1 = self.__data2[:]

         print "__data1: ", self.__data1, object.__repr__(self.__data1)
         print "__data2: ", self.__data2, object.__repr__(self.__data1)

And your tests now become:
 >>> m1 = my()
__data1:  [] <list object at 0x00EF2A80>
__data2:  [] <list object at 0x00A99620>
__data1:  [2005, 8, 9, 10, 5, 54, 1, 221, 1] <list object at 0x00A9AFD0>
__data2:  [2005, 8, 9, 10, 5, 54, 1, 221, 1] <list object at 0x00A99620>
 >>> m2 = my()
__data1:  [] <list object at 0x00EF2A80>
__data2:  [2005, 8, 9, 10, 5, 54, 1, 221, 1] <list object at 0x00A99620>
__data1:  [2005, 8, 9, 10, 5, 54, 1, 221, 1, 2005, 8, 9, 10, 5, 56, 1, 
221, 1] <list object at 0x00A9D1C0>
__data2:  [2005, 8, 9, 10, 5, 54, 1, 221, 1, 2005, 8, 9, 10, 5, 56, 1, 
221, 1] <list object at 0x00A99620>

Notice how the 'address' of __data1 changes after executing the 
constructor.  This change, made in __init__, is reflected only in that 
instance's copy of the name.  Also notice how __data2 in both m1 and m2 
share the same address; this is why changes in one instance are 
reflected in the others.



More information about the Python-list mailing list