How to get a reference of the 'owner' class to which a method belongs in Python 3.X?

Cosmia Luna cosmius at gmail.com
Sun Mar 18 05:42:20 EDT 2012


I think I got the way to handle it but with small problem and probably at
unnecessary performance cost. If you're going to use it, be sure rewrite the
code and remove the lines which you don't need. Annnnd, test them, the code
below is only tested on py3.2, and may contains a lot of bugs even in py3.2.
You don't need it in py2.X, really.

----------------------------------BEGIN PYTHON----------------------------------
from functools import wraps
from types import FunctionType

CLASS_REF = 'im_class'

class Py2Type(type):
    def __init__(cls, name, bases, dict_):
        for k, v in dict_.items(): #ref3
            if isinstance(v, FunctionType):
                setattr(v, CLASS_REF, cls)
        for base in bases:
            for k, v in base.__dict__.items():
                if isinstance(v, FunctionType) and k not in dict_:
                    @wraps(v)
                    def wrapper(*args, **kwargs):
                        return v(*args, **kwargs)
                    setattr(wrapper, CLASS_REF, cls)
                    dict_[k] = wrapper
                    setattr(cls, k, wrapper) #ref1
        type.__init__(cls, name, bases, dict_) #ref2

Py2TypeBase = Py2Type('Py2TypeBase', (object, ), {})
-----------------------------------END PYTHON-----------------------------------

And any class inherit(directly or indirectly) from Py2TypeBase can have them
unbound method has a 'im_class' attribute reference to the owner class.

Usage:

Just subclass Py2TypeBase and write anything you want.

----------------------------------BEGIN PYTHON----------------------------------
class Foo(Py2TypeBase):
    def get(self): pass
    def set(self): pass

class Bar(Foo):
    def get(self): pass

assert Foo.get.im_class is Foo
assert Foo.set.im_class is Foo
assert Bar.get.im_class is Bar
assert Bar.set.im_class is Bar

# the code above works, but only the explicitly defined will has the
# im_class attribute, so

assert Foo.__init__.im_class is Foo # this doesn't work.

-----------------------------------END PYTHON-----------------------------------

But it seems that the last line(#ref2) in the Py2Type.__init__ does not work at
all. It seems really weird, 'type' is an instance of 'type' itself, I'm not sure
if I'm calling the unbound method __init__ or bound method __init__.

And the original code does not have the line(#ref1), but because line(#ref2)
does not work, I added them.

It seems type.__new__ calls type.__init__ before it calls Py2Type.__init__,
because dict_ is already copied to cls.__dict__ at line(#ref3).

But 'type' is written in C or some other, it's beyond my ability to read the
code. Can anyone tell me what python does when a class block is fully evaluated
kindly?

Regards,
Cosmia



More information about the Python-list mailing list