views:

33

answers:

1

Say I want to make a decorator for methods defined in a class. I want that decorator, when invoked, to be able to set an attribute on the class defining the method (in order to register it in a list of methods that serve a particular purpose).

In Python 2, the im_class method accomplishes this nicely:

def decorator(method):
  cls = method.im_class
  cls.foo = 'bar'
  return method

However, in Python 3, no such attribute (or a replacement for it) seems to exist. I suppose the idea was that you could call type(method.__self__) to get the class, but this does not work for unbound methods, since __self__ == None in that case.

NOTE: This question is actually a bit irrelevant for my case, since I've chosen instead to set an attribute on the method itself and then have the instance scan through all of its methods looking for that attribute at the appropriate time. I am also (currently) using Python 2.6. However, I am curious if there is any replacement for the version 2 functionality, and if not, what the rationale was for removing it completely.

EDIT: I just found this question. This makes it seem like the best solution is just to avoid it like I have. I'm still wondering why it was removed though.

+4  A: 

The point you appear to be missing is, in Python 3 the "unbound method" type has entirely disappeared -- a method, until and unless it's bound, is just a function, without the weird "type-checking" unbound methods used to perform. This makes the language simpler!

To wit...:

>>> class X:
...   def Y(self): pass
... 
>>> type(X.Y)
<class 'function'>

and voila -- one less subtle concept and distinction to worry about. Such simplifications are the core advantage of Python 3 wrt Python 2, which (over the years) had been accumulating so many subtleties that it was in danger (if features kept being added to it) of really losing its status as a simple language. With Python 3, simplicity is back!-)

Alex Martelli
That makes sense. I didn't even realize there was extra functionality for methods like the first-argument type checking--I just thought they would be normal functions with a few extra attributes. With that, I can completely understand the removal.
Tim Yates
@Tim, yes, the check that the first argument was of an instance of the `.im_class` (including subclasses thereof of course) is why `im_class` was kept in the first place (and the same layer of indirectness wrapped around functions to make unbound methods, as needs to be wrapped anyway to make bound ones). The underlying function always was (and still is for _bound_ methods) the `.im_func`, BTW, never the method object itself.
Alex Martelli