2

When I create a decorator for a class method, it always receives the method as of type "function".

However, when I play around with things a bit, I only get back bound methods:

class Test(object):
 def save(self):
 print "Save called"
 def func(self):
 print "Func called"

And then:

>>> type(Test.func)
<type 'instancemethod'>
>>> type(Test().func)
<type 'instancemethod'>

What I would ultimately like to do is create a class method decorator, which also decorates some other method on the same class. How would I go about doing this?

unutbu
886k197 gold badges1.9k silver badges1.7k bronze badges
asked Sep 20, 2011 at 11:40
1
  • 1
    Test.func is not a bound method. Commented Sep 20, 2011 at 11:47

2 Answers 2

3

This is impossible; you'd have to use a class decorator or metaclass instead. Decorator syntax

class Foo(object):
 @dec
 def bar(self): pass

means

class Foo(object)
 def bar(self): pass
 bar = dec(bar)

where a class definition is processed as: execute the body, then gather the definitions and wrap them in a class object. I.e., decoration is done before the class comes into existence.

answered Sep 20, 2011 at 11:43
Sign up to request clarification or add additional context in comments.

Comments

2

It depens on the order of stuff that happens.

If you take a "normal" method. the following happens:

class Test(object):
 def save(self):
 print "Save called"
 def func(self):
 print "Func called"
>>> Test.__dict__["func"]
<function func at 0x00B43E30>
>>> Test.func
<unbound method Test.func>

Should be the same. What happens here? Well, look:

>>> f = Test.__dict__["func"]
>>> m = f.__get__(None, Test)
>>> f, m
(<function func at 0x00B43E30>, <unbound method Test.func>)

The first is the original function object, the second one the method object which is created when doing an actual method call.

Furthermore, if you have an instance:

>>> t = Test()
>>> t.func
<bound method Test.func of <__main__.Test object at 0x00B48AB0>>
>>> f.__get__(t, Test)
<bound method Test.func of <__main__.Test object at 0x00B48AB0>>

So this happens on attribute access.

Now to your question:

The reason this happens is because the original function is present in the class's __dict__. The method object creation happens on access.

answered Sep 20, 2011 at 12:18

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.