From: Ani on 1 Apr 2010 14:56 Hi All: I am just a beginner in python. Can anyone please tell me what is wrong with this piece of code? import copy class BaseDummyObject(object): def __init__(self): pass def __getattr__(self, item): try: return self.__dict__.__getitem__(item) except KeyError: print "Attribute Error: attr %s of class %s non-existent!" %(item, self.__class__.__name__) class DummyObject(BaseDummyObject): pass def main(): bar = 3 obj = DummyObject() obj.foo = bar obj.me = obj newobj = copy.deepcopy(obj) if __name__ == "__main__": main() So when I do this, I get: Attribute Error: attr __deepcopy__ of class DummyObject non-existent! Attribute Error: attr __getnewargs__ of class DummyObject non- existent! Traceback (most recent call last): File "C:\Workspace\QA3.0\Python_Lib\Mobidia\RemoteManager \test_code.py", line 39, in <module> main() File "C:\Workspace\QA3.0\Python_Lib\Mobidia\RemoteManager \test_code.py", line 30, in main newobj = copy.deepcopy(obj) File "C:\Python26\lib\copy.py", line 181, in deepcopy rv = reductor(2) TypeError: 'NoneType' object is not callable Any help will be really appreciated.
From: Robert Kern on 1 Apr 2010 15:10 On 2010-04-01 13:56 PM, Ani wrote: > Hi All: > > I am just a beginner in python. Can anyone please tell me what is > wrong with this piece of code? > > import copy > class BaseDummyObject(object): > > def __init__(self): > pass > > def __getattr__(self, item): > try: > return self.__dict__.__getitem__(item) > except KeyError: > print "Attribute Error: attr %s of class %s non-existent!" > %(item, > > self.__class__.__name__) You need to raise an AttributeError here. Otherwise, it implicitly returns None for all attributes not in the __dict__ and thus confusing the copy.deepcopy() code. -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco
From: Ani on 1 Apr 2010 17:52 On Apr 1, 12:10 pm, Robert Kern <robert.k...(a)gmail.com> wrote: > On 2010-04-01 13:56 PM, Ani wrote: > > > > > Hi All: > > > I am just a beginner in python. Can anyone please tell me what is > > wrong with this piece of code? > > > import copy > > class BaseDummyObject(object): > > > def __init__(self): > > pass > > > def __getattr__(self, item): > > try: > > return self.__dict__.__getitem__(item) > > except KeyError: > > print "Attribute Error: attr %s of class %s non-existent!" > > %(item, > > > self.__class__.__name__) > > You need to raise an AttributeError here. Otherwise, it implicitly returns None > for all attributes not in the __dict__ and thus confusing the copy.deepcopy() code. > Thanks Robert. So I raised the exception and now everything looks good. So what's happening here? When a certain attribute is not available in the __dict__ and an exception is raised, who's catching it? Ani
From: Robert Kern on 1 Apr 2010 18:18 On 2010-04-01 16:52 PM, Ani wrote: > On Apr 1, 12:10 pm, Robert Kern<robert.k...(a)gmail.com> wrote: >> On 2010-04-01 13:56 PM, Ani wrote: >> >> >> >>> Hi All: >> >>> I am just a beginner in python. Can anyone please tell me what is >>> wrong with this piece of code? >> >>> import copy >>> class BaseDummyObject(object): >> >>> def __init__(self): >>> pass >> >>> def __getattr__(self, item): >>> try: >>> return self.__dict__.__getitem__(item) >>> except KeyError: >>> print "Attribute Error: attr %s of class %s non-existent!" >>> %(item, >> >>> self.__class__.__name__) >> >> You need to raise an AttributeError here. Otherwise, it implicitly returns None >> for all attributes not in the __dict__ and thus confusing the copy.deepcopy() code. >> > > Thanks Robert. So I raised the exception and now everything looks > good. So what's happening here? When a certain attribute is not > available in the __dict__ and an exception is raised, who's catching > it? copy.deepcopy(), in this case, or one of the functions it calls. You can use traceback.print_stack() to see who is attempting to get the attribute. It is checking for certain methods on the object which control how the object gets seralized. copy.deepcopy() uses the same mechanism as pickle to serialize and reconstruct the object in memory. -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco
From: Bruno Desthuilliers on 2 Apr 2010 04:45
Ani a �crit : > Hi All: > > I am just a beginner in python. Can anyone please tell me what is > wrong with this piece of code? Robert already addressed your problem, so I'll just comment on a couple other points: > import copy > class BaseDummyObject(object): > > def __init__(self): > pass This initializer is at best useless. > def __getattr__(self, item): The second parameter to __getattr__ is the name that is looked for, so better to name it "name" or "attrname" or... > try: > return self.__dict__.__getitem__(item) __getitem__ - like most __magicmethods__ - provides support for the "subscript" operator, and as such is not supposed to be explicitely called (except for a couple corner cases). This should just be: return self.__dict__[item] > except KeyError: > print "Attribute Error: attr %s of class %s non-existent!" > %(item, self.__class__.__name__) The canonical AttributeError message is "'<classname>' object has no attribute '<attrname>'" - ok, doesn't matter much, but being consistent with the core language is usually a good idea IMHO !-) And now for the most import point: __getattr__ is only called as a *last* resort. That is, after the attribute lookup mechanism will have tried *and failed* to find the name in the instance's __dict__. HTH |