From: Ani on
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
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
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
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
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