Why doesnt __getattr__ with decorator dont call __get_method in decorator

G

glomde

Hi,

I tried to write a decorator for that should be for methods but for
some reasons
it doens seem to work when you try to do it on the __getattr__ method
in a class.
Could anybody give some hints why this is?

Example:
class decoratorTest(object):
def __init__(self, func):
self.func = func

def __get__(self, instance, cls=None):
print "__get__", instance
self.instance = instance
return self

def __call__(self, *args, **kwds):
return self.func(self.instance, *args, **kwds)

class MyClass1(object):

@decoratorTest
def decoratorTestFunc(self):
print "hello1"

@decoratorTest
def __getattr__(self,name):
print "hello2"


a = MyClass1()
a.decoratorTestFunc() # This works since the __get__ method is called
and the instance is retreived
a.test # This doesnt call the __get__ !!!

Output
__get__ <__main__.MyClass1 object at 0x4012baac>
hello1
Traceback (most recent call last):
File "/home/tonib/test.py", line 27, in ?
a.test
File "/home/tonib/test.py", line 12, in __call__
return self.func(self.instance, *args, **kwds)
AttributeError: 'decoratorTest' object has no attribute 'instance'
 
A

Alex Martelli

glomde said:
Hi,

I tried to write a decorator for that should be for methods but for
some reasons
it doens seem to work when you try to do it on the __getattr__ method
in a class.
Could anybody give some hints why this is? ....
a.test # This doesnt call the __get__ !!!

Output
__get__ <__main__.MyClass1 object at 0x4012baac>
hello1
Traceback (most recent call last):
File "/home/tonib/test.py", line 27, in ?
a.test
File "/home/tonib/test.py", line 12, in __call__
return self.func(self.instance, *args, **kwds)
AttributeError: 'decoratorTest' object has no attribute 'instance'

What Python release are you using? With Python 2.5, your code gives me
instead:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "a.py", line 11, in __call__
return self.func(self.instance, *args, **kwds)
TypeError: __getattr__() takes exactly 2 arguments (3 given)
so there would seem to be some "mis-alignment" wrt the problems you
observe...


Alex
 
G

glomde

What Python release are you using? With Python 2.5, your code gives me
instead:


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "a.py", line 11, in __call__
return self.func(self.instance, *args, **kwds)
TypeError: __getattr__() takes exactly 2 arguments (3 given)



so there would seem to be some "mis-alignment" wrt the problems you
observe...

Alex

I was using 2.4 but I downloaded and installed ActivePython2.5.0.0 and
for I get the same message as in my original email.
What python version do you use more exactly?

/T
 
7

7stud

Hi,

I tried to write a decorator for that should be for methods but for
some reasons
it doens seem to work when you try to do it on the __getattr__ method
in a class.
Could anybody give some hints why this is?

All you have to do is decorator should methods write be for reason it
works with class __getattr__ in!
 
A

Arnaud Delobelle

What Python release are you using? With Python 2.5, your code gives me
instead:


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "a.py", line 11, in __call__
return self.func(self.instance, *args, **kwds)
TypeError: __getattr__() takes exactly 2 arguments (3 given)



so there would seem to be some "mis-alignment" wrt the problems you
observe...

I get this error with python 2.4 when I do

a.__getattr__('test') # This sets the 'instance' attribute as __get__
is called
a.test # __get__ is not called but 'instance' is set

To get python to run the __get__ method I think you have to call
__getattr__ explicitly:
a.__getattr__('test')

If you do:
a.test
python follows a different routine: it checks for the existence of the
attribute, then check if there is a __getattr__ attribute. Now the
speculative bit: then I conjecture that python assumes that
__getattr__ is a function with two arguments and directly passes them
on to it. Indeed

type(a).__dict__['__getattr__'](a, 'test')

seems to produce the same errors as a.test, whether the instance
attribute is set or not.
And this explain why there are too many arguments (error message
above).
 
G

glomde

To get python to run the __get__ method I think you have to call
__getattr__ explicitly:
a.__getattr__('test')

If you do:
a.test
python follows a different routine: it checks for the existence of the
attribute, then check if there is a __getattr__ attribute. Now the
speculative bit: then I conjecture that python assumes that
__getattr__ is a function with two arguments and directly passes them
on to it. Indeed

type(a).__dict__['__getattr__'](a, 'test')

seems to produce the same errors as a.test, whether the instance
attribute is set or not.
And this explain why there are too many arguments (error message
above).

So is this a python bug? I assumed it was seen as function but dont
understand why it is like this. But interesting that if you call
__getattr__ explicitly it works.

Intuitevely I would assumet that the same route should be followed
in both case.

Maybe it is because __getattr__ is called only when you have an
exception.

/T
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top