Can I find out (dynamically) where a method is defined?

A

allendowney

Hi All.

In a complex inheritance hierarchy, it is sometimes difficult to find
where a
method is defined. I thought it might be possible to get this info
from the
method object itself, but it looks like maybe not. Here is the test
case I tried:

class A(object):
def method():
pass

class B(A):
pass

a = A()
b = B()

print a.method
print b.method

Since B inherits method from A, I thought that printing b.method might
tell
me that the definition is in A, but no. Here's the output:

<bound method A.method of <__main__.A object at 0xb7d55e0c>>
<bound method B.method of <__main__.B object at 0xb7d55e2c>>

This in indistinguishable from the case where B overrides method.

So, is there any way to inspect a method to see where (in what class)
it
is defined?

Thanks!
Allen
 
M

Maric Michaud

Le Monday 09 June 2008 17:28:45 (e-mail address removed), vous avez écrit :
So, is there any way to inspect a method to see where (in what class)
it
is defined?

In [56]: class a(object) :
def a() : return
def b() : return
....:
....:

In [59]: class b(a) :
def b() : return
def c() : return
....:
....:

In [62]: i=b()

In [63]: for m in 'a', 'b', 'c' :
....: print [ t for t in type(i).mro() if m in dir(t) ]
....:
....:
[<class '__main__.a'>]
[<class '__main__.b'>, <class '__main__.a'>]
[<class '__main__.b'>]

mro stands for "method resolution order", check the reference on this
and "super", it worths the effort.

--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 4 26 88 00 97
Mobile: +33 6 32 77 00 21
 
L

Lie

Hi All.

In a complex inheritance hierarchy, it is sometimes difficult to find
where a
method is defined.  I thought it might be possible to get this info
from the
method object itself, but it looks like maybe not.  Here is the test
case I tried:

class A(object):
    def method():
        pass

class B(A):
    pass

a = A()
b = B()

print a.method
print b.method

Since B inherits method from A, I thought that printing b.method might
tell
me that the definition is in A, but no.  Here's the output:

<bound method A.method of <__main__.A object at 0xb7d55e0c>>
<bound method B.method of <__main__.B object at 0xb7d55e2c>>

This in indistinguishable from the case where B overrides method.

So, is there any way to inspect a method to see where (in what class)
it
is defined?

I don't know if there is other easier methods, but if you have access
to the source code, you can always add a print function.

class A(object):
def method(self):
print 'Entering A.method'
... The rest of the codes ...

class B(A):
def method(self):
print 'Entering B.method'
... The rest of the codes ...

class C(A):
pass

If you don't have access to the source code, that means you shouldn't
need to worry about it.

A rather odd thing I just noticed is this:

class A(object):
def method(self):
pass

class B(A):
def method(self):
pass

class C(A):
pass

print A.method == B.method ## False
print A.method == C.method ## True
 
G

Gary Herron

You might try the inspect module. It can give you lots of information
about a method (even including the file name and line number where it
was defined). Poke around and perhaps you can find exactly what you are
looking for.

Gary Herron
 
A

allendowney

Thanks Maric! That's very close to what I want, although using dir()
can be misleading because if you invoke it on class B you get all of
class A's methods as well. I took your idea and wrote it up like
this:

def find_defining_class(obj, meth_name):
"""find and return the class object that will provide
the definition of meth_name (as a string) if it is
invoked on obj.
"""
for ty in type(obj).mro():
if meth_name in ty.__dict__:
return ty
return None

Cheers,
Allen



Le Monday 09 June 2008 17:28:45 (e-mail address removed), vous avez écrit :
So, is there any way to inspect a method to see where (in what class)
it
is defined?

In [56]: class a(object) :
    def a() : return
    def b() :  return
   ....:
   ....:

In [59]: class b(a) :
    def b() : return
    def c() : return
   ....:
   ....:

In [62]: i=b()

In [63]: for m in 'a', 'b', 'c' :
   ....:     print [ t for t in type(i).mro() if m in dir(t) ]
   ....:
   ....:
[<class '__main__.a'>]
[<class '__main__.b'>, <class '__main__.a'>]
[<class '__main__.b'>]

mro stands for "method resolution order", check the reference on this
and "super", it worths the effort.
 
M

Maric Michaud

Le Monday 09 June 2008 19:03:18 (e-mail address removed), vous avez écrit :
Thanks Maric! That's very close to what I want, although using dir()
can be misleading because if you invoke it on class B you get all of
class A's methods as well. I took your idea and wrote it up like
this:

def find_defining_class(obj, meth_name):
"""find and return the class object that will provide
the definition of meth_name (as a string) if it is
invoked on obj.
"""
for ty in type(obj).mro():
if meth_name in ty.__dict__:
return ty
return None

Cheers,
Allen

Oh ! you're just right, my first writing of this was :

for m in 'a', 'b', 'c' :
print [ t for t in type(i).mro() if m in t.__dict__ ]

which I carelessly ad wrongly rewrote using dir while posting.
Sorry.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top