Bugs item #1583060, was opened at 2006-10-23 14:13 Message generated for change (Comment added) made by santaroga You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1583060&group_id=5470
Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: Type/class unification Group: Python 2.4 Status: Open Resolution: None Priority: 5 Private: No Submitted By: EricDaigno (santaroga) Assigned to: Nobody/Anonymous (nobody) Summary: class member inconsistancies Initial Comment: Hi... When coding rapid classes I stumbled upon a strange behaviour in the way python deals with data membership of it's instances (new style) when using C struct like container classes behaviour changes when data members are declared in the class itself as opposed to be declared in the __init__ method... I understand that python does not perform any sort of initialization outside of __init__ but this really create confusion as to what is allowed and what is not and is clear inconstancy that is either a language usability bug of a plain buf in class creation-initialization. The problem happens when declaring a class that does not contain __init__ method override but contains a bunch of data elements that are initialized in the declaration. Expected behaviour would be that when a new instance is created the python interpreter would create a new instance and initialize the members as stated in the class declaration and then call the __init__ method (from object or the overriden __init__ from the class) The reality is quite different. Immutables (string) are dealt with correctly but mutables (list, dict) are initialized only once. Every subsequent instantiation of the class will therefore see new instances of member immutables objects but will SHARE instances of the member mutables. I have created a small programm that illustrate the behaviour : ------------------------------------------------CodeStart class A(object): def __init__(self): self.argsList = [] self.dictArgs = {} self.ARG1 = "" self.ARG2 = "" def multUnnammedArgs(self, *argsList): if not argsList is None: self.argsList += argsList def multNAmmedArgument(self, **argDict): if not argDict is None: for i in argDict.iteritems(): self.dictArgs[i[0]] = i[1] def mixedArguments(self, ARG1, ARG2, *argList, **argDict): self.ARG1 = ARG1 self.ARG2 = ARG2 self.multUnnammedArgs(*argList) self.multNAmmedArgument(**argDict) def __str__(self): string = "Object A :" string += "\n\t\tARG1=" + self.ARG1 string += "\n\t\tARG2=" + self.ARG2 string += "\n\tUnnammed Arguments" for a in self.argsList: string += "\n\t\t" + a string += "\n\tNamed Arguments" for a in self.dictArgs.iteritems(): string += "\n\t\t" + a[0] + "=" + a[1] return string if __name__ == '__main__': obj = A() obj.multUnnammedArgs("arg1", "arg2", "arg3") print obj obj.multNAmmedArgument(TOTO = "toto", TITI = "titi", TaTa = "tATa") print obj obj.mixedArguments(ARG1="ZeArg1", ARG2="ZeArg2", TOTO2 = "toto2", TITI2 = "titi2", TaTa2 = "tATa2") print obj -----------------------------------------------Code End Here is the dump of my python environment ---------------------------------------------Dump Start [EMAIL PROTECTED] ~]$ python -v # installing zipimport hook import zipimport # builtin # installed zipimport hook # /lesia/toolbox/python/lib/python2.4/site.pyc matches /lesia/toolbox/python/lib/python2.4/site.py import site # precompiled from /lesia/toolbox/python/lib/python2.4/site.pyc # /lesia/toolbox/python/lib/python2.4/os.pyc matches /lesia/toolbox/python/lib/python2.4/os.py import os # precompiled from /lesia/toolbox/python/lib/python2.4/os.pyc import posix # builtin # /lesia/toolbox/python/lib/python2.4/posixpath.pyc matches /lesia/toolbox/python/lib/python2.4/posixpath.py import posixpath # precompiled from /lesia/toolbox/python/lib/python2.4/posixpath.pyc # /lesia/toolbox/python/lib/python2.4/stat.pyc matches /lesia/toolbox/python/lib/python2.4/stat.py import stat # precompiled from /lesia/toolbox/python/lib/python2.4/stat.pyc # /lesia/toolbox/python/lib/python2.4/UserDict.pyc matches /lesia/toolbox/python/lib/python2.4/UserDict.py import UserDict # precompiled from /lesia/toolbox/python/lib/python2.4/UserDict.pyc # /lesia/toolbox/python/lib/python2.4/copy_reg.pyc matches /lesia/toolbox/python/lib/python2.4/copy_reg.py import copy_reg # precompiled from /lesia/toolbox/python/lib/python2.4/copy_reg.pyc # /lesia/toolbox/python/lib/python2.4/types.pyc matches /lesia/toolbox/python/lib/python2.4/types.py import types # precompiled from /lesia/toolbox/python/lib/python2.4/types.pyc # /lesia/toolbox/python/lib/python2.4/warnings.pyc matches /lesia/toolbox/python/lib/python2.4/warnings.py import warnings # precompiled from /lesia/toolbox/python/lib/python2.4/warnings.pyc # /lesia/toolbox/python/lib/python2.4/linecache.pyc matches /lesia/toolbox/python/lib/python2.4/linecache.py import linecache # precompiled from /lesia/toolbox/python/lib/python2.4/linecache.pyc import encodings # directory /lesia/toolbox/python/lib/python2.4/encodings # /lesia/toolbox/python/lib/python2.4/encodings/__init__.pyc matches /lesia/toolbox/python/lib/python2.4/encodings/__init__.py import encodings # precompiled from /lesia/toolbox/python/lib/python2.4/encodings/__init__.pyc # /lesia/toolbox/python/lib/python2.4/codecs.pyc matches /lesia/toolbox/python/lib/python2.4/codecs.py import codecs # precompiled from /lesia/toolbox/python/lib/python2.4/codecs.pyc import _codecs # builtin # /lesia/toolbox/python/lib/python2.4/encodings/aliases.pyc matches /lesia/toolbox/python/lib/python2.4/encodings/aliases.py import encodings.aliases # precompiled from /lesia/toolbox/python/lib/python2.4/encodings/aliases.pyc # /lesia/toolbox/python/lib/python2.4/encodings/utf_8.pyc matches /lesia/toolbox/python/lib/python2.4/encodings/utf_8.py import encodings.utf_8 # precompiled from /lesia/toolbox/python/lib/python2.4/encodings/utf_8.pyc Python 2.4.2 (#1, Aug 1 2006, 16:57:48) [GCC 4.0.2 20051125 (Red Hat 4.0.2-8)] on linux2 Type "help", "copyright", "credits" or "license" for more information. dlopen("/lesia/toolbox/python/lib/python2.4/lib-dynload/readline.so", 2); import readline # dynamically loaded from /lesia/toolbox/python/lib/python2.4/lib-dynload/readline.so >>> -------------------------------------------Dump end ---------------------------------------------------------------------- >Comment By: EricDaigno (santaroga) Date: 2006-10-23 14:17 Message: Logged In: YES user_id=1628112 darn.... Attached the wrong code ... My bad, sorry about that. Here is the correct test programm ------------------------------------------------Code Start class A(object): aString = "first init..." aList = [] aDict = {} def __str__(self): string = "" string += "_____________" + self.aString string += "\n\t aList= " for elem in self.aList: string += "\n\t\t" + elem string += "\n\t aDict= " for elem in self.aDict.keys(): string += "\n\t\t" + elem + "=" + self.aDict[elem] string += "\n--------------" return string if __name__ == '__main__': firstInstance = A() print firstInstance print "This is as expected from the class declaration." print "Members are initialized as declared in the class " print "and the new instance is clean" firstInstance.aString = "firstInstance's String" firstInstance.aList.append("firstInstance first List element") firstInstance.aList.append("firstInstance second List element") firstInstance.aList.append("firstInstance third List element") firstInstance.aDict["firstInstance"] = "SpecificToFirstInstance" firstInstance.aDict["whatever"] = "FirstInstance's Whatever" print firstInstance print "Again... So far so good" print "" secondInstance = A() print secondInstance print "This however is completely unsuspected." print "The class initialized the string properly but " print "mutables have not been replaced with the new instances of list and dict" print "as we soiuld expect from the class declaration" print "It gets beter..." secondInstance.aString = "secondInstance String" secondInstance.aList.append("secondInstance first List element") secondInstance.aList.append("secondInstance second List element") secondInstance.aList.append("secondInstance third List element") secondInstance.aDict["secondInstance"] = "SpecificToSecondInstance" secondInstance.aDict["whatever"] = "econdInstance's Whatever" print firstInstance print secondInstance print "I therefore conclude that when dealing with " print "'default' initlialization that Immutables are dealt with properly but" print "mutables mutables are not initialized." print "This behaviour is contradictory from what one would expect when " print "declaring a simple class that acts like a C struct" ------------------------------------------Code End ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1583060&group_id=5470 _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com