py2.1->py2.3.3 __getattr__ confusion

H

Holger Joukl

Hi there,
please excuse my rather lengthy post.
With introduction of the new style classes, something
seems to have changed for __getattr__ hooks, even
for classic classes:

getattr.py:
class A: # classic!
def __getattr__(self, attr):
print "-->A.__getattr__"
print "attr=", attr
print "<--A.__getattr__"
return self.__dict__[attr]

a = A()
print "a.__dict__:", a.__dict__
a.foo()
x = a.foo
print "a.foo:", a.foo

$ python2.1 getattr2.py
a.__dict__: {}
A.foo()
a.foo: <method A.foo of A instance at c37d0>

$ python2.3 getattr2.py
a.__dict__: {}
A.foo()
a.foo: -->A.__getattr__
attr= __repr__
<--A.__getattr__
Traceback (most recent call last):
File "getattr2.py", line 22, in ?
print "a.foo:", a.foo
File "getattr2.py", line 6, in __getattr__
return self.__dict__[attr]
KeyError: '__repr__'

I didn´t find the explanation for this behaviour in the
"what´s new" sections and the docs (and googling).
Probably I missed it - any hints?

Formerly, the instance attribute lookup mechanism was:
1. local __dict__
2. corresponding class definition
3. __getattr__

Now, this seems to work different for the a.foo lookup,
but not for the a.foo() method invocation?!

If I change my class A __getattr__ method in the following way,
I seem to workaround the problem:

class A:
def __getattr__(self, attr):
print "-->A.__getattr__"
print "attr=", attr
print "<--A.__getattr__"
return self.__dict__[attr]
# Use this Try-except-raise AttributeError to get the same
behaviour
# in python 2.2+ as in python 1.5.2
# try:
# return self.__dict__[attr]
# except KeyError:
# raise AttributeError

Is this a valid workaround to apply to old __getattr__ hooks?

Thanks for any hints,
Holger

Der Inhalt dieser E-Mail ist vertraulich. Falls Sie nicht der angegebene
Empfänger sind oder falls diese E-Mail irrtümlich an Sie adressiert wurde,
verständigen Sie bitte den Absender sofort und löschen Sie die E-Mail
sodann. Das unerlaubte Kopieren sowie die unbefugte Übermittlung sind nicht
gestattet. Die Sicherheit von Übermittlungen per E-Mail kann nicht
garantiert werden. Falls Sie eine Bestätigung wünschen, fordern Sie bitte
den Inhalt der E-Mail als Hardcopy an.

The contents of this e-mail are confidential. If you are not the named
addressee or if this transmission has been addressed to you in error,
please notify the sender immediately and then delete this e-mail. Any
unauthorized copying and transmission is forbidden. E-Mail transmission
cannot be guaranteed to be secure. If verification is required, please
request a hard copy version.
 
P

Peter Otten

Holger said:
With introduction of the new style classes, something
seems to have changed for __getattr__ hooks, even
for classic classes:

Here is what I think it boils down to:

<joukl_getattr.py>
class A:
def __getattr__(self, name):
raise Exception

repr(A())
</joukl_getattr.py>

$ python2.1 joukl_getattr.py
$ python2.2 joukl_getattr.py
$ python2.3 joukl_getattr.py
Traceback (most recent call last):
File "joukl_getattr.py", line 20, in ?
repr(A())
File "joukl_getattr.py", line 18, in __getattr__
raise Exception
Exception

<joukl_getattr2.py>
class A:
def __getattr__(self, name):
print name
raise AttributeError

repr(A())
</joukl_getattr2.py>

$ python2.2 joukl_getattr2.py
__repr__
$ python2.3 joukl_getattr2.py
__repr__

That is, starting with Python 2.3 the repr() and str() functions no longer
mask exceptions other than AttributeError. Solution: make sure you raise an
AttributeError instead of the current KeyError for nonexistent attributes.


Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top