Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

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

0 views
Skip to first unread message

allen...@gmail.com

unread,
Jun 9, 2008, 11:28:45 AM6/9/08
to
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


Maric Michaud

unread,
Jun 9, 2008, 12:01:25 PM6/9/08
to pytho...@python.org
Le Monday 09 June 2008 17:28:45 allen...@gmail.com, 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

Lie

unread,
Jun 9, 2008, 12:12:25 PM6/9/08
to

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

Gary Herron

unread,
Jun 9, 2008, 12:28:42 PM6/9/08
to pytho...@python.org

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

allen...@gmail.com

unread,
Jun 9, 2008, 1:03:18 PM6/9/08
to
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

On Jun 9, 12:01 pm, Maric Michaud <ma...@aristote.info> wrote:

Maric Michaud

unread,
Jun 10, 2008, 2:52:48 AM6/10/08
to pytho...@python.org
Le Monday 09 June 2008 19:03:18 allen...@gmail.com, 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.

--
_____________

Maric Michaud

0 new messages