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

How to determine which method was used in an inheritance heirarchy?

1 view
Skip to first unread message

Erik Jones

unread,
Jul 15, 2007, 11:51:42 PM7/15/07
to pytho...@python.org
Say you're given a call event frame for a method call. How can you
tell if the code being executed came from a super class of the object
or class the method was called on?

Erik Jones

Software Developer | Emma®
er...@myemma.com
800.595.4401 or 615.292.5888
615.292.0777 (fax)

Emma helps organizations everywhere communicate & market in style.
Visit us online at http://www.myemma.com


Michele Simionato

unread,
Jul 16, 2007, 12:23:08 AM7/16/07
to
On Jul 16, 5:51 am, Erik Jones <e...@myemma.com> wrote:
> Say you're given a call event frame for a method call. How can you
> tell if the code being executed came from a super class of the object
> or class the method was called on?
>
> Erik Jones

You look if the method was defined in self.__class__.__dict__.

Michele Simionato

Erik Jones

unread,
Jul 16, 2007, 1:18:35 AM7/16/07
to Michele Simionato, pytho...@python.org

That doesn't seem to cover calling super class __init__ methods.

Michele Simionato

unread,
Jul 16, 2007, 1:53:40 AM7/16/07
to
On Jul 16, 7:18 am, Erik Jones <e...@myemma.com> wrote:
> On Jul 15, 2007, at 11:23 PM, Michele Simionato wrote:
>
> > On Jul 16, 5:51 am, Erik Jones <e...@myemma.com> wrote:
> >> Say you're given a call event frame for a method call. How can you
> >> tell if the code being executed came from a super class of the object
> >> or class the method was called on?
>
> >> Erik Jones
>
> > You look if the method was defined in self.__class__.__dict__.
>
> > Michele Simionato
>
> That doesn't seem to cover calling super class __init__ methods.
>

I am probably missing something. In the following code the
method check_init checks if the current instance
possess an __init__ or if it just inherits one
from the ancestors. Is this what you want?

class B(object):
def __init__(self):
'something'
def check_init(self):
if '__init__' in self.__class__.__dict__:
print 'possesses __init__'
else:
print 'inherits __init__'

class C(B):
'something else'
def __init__(self):
print 'calling C.__init__'

class D(B):
pass

c = C()
d = D()

c.check_init() #possesses __init__
d.check_init() #inherits __init__

Erik Jones

unread,
Jul 16, 2007, 2:31:18 AM7/16/07
to Michele Simionato, pytho...@python.org

Ok, I see how I was pretty vague with my original questions. Given
the pattern where you need to call a base class's constructor (or,
other overriden method of the same name as that being called on the
child class object):

class A(object):
def __init__(self):
print self.__class__.__name__

class B(A):
def __init__(self):
A.__init__(self)
print self.__class__.__name__

B()

This will output:

B
B

How can I get

A
B

Erik Jones

unread,
Jul 16, 2007, 2:56:18 AM7/16/07
to Michele Simionato, pytho...@python.org

On Jul 16, 2007, at 1:31 AM, Erik Jones wrote:

> Ok, I see how I was pretty vague with my original questions.
> Given the pattern where you need to call a base class's constructor
> (or, other overriden method of the same name as that being called
> on the child class object):
>
> class A(object):
> def __init__(self):
> print self.__class__.__name__
>
> class B(A):
> def __init__(self):
> A.__init__(self)
> print self.__class__.__name__
>
> B()
>
> This will output:
>
> B
> B
>
> How can I get
>
> A
> B

Perhaps an even better example of what I'm trying to do would be in
order (this is minus any exception handling):

import sys

def mytrace(frame, event, arg):
if event == 'call':
func_name = frame.f_code.co_name

if func_name in frame.f_locals['self'].__class__.__dict__:
print frame.f_locals['self'].__class__.__name__
else:
for base in frame.f_locals['self'].__class__.__bases__:
if func_name in base.__dict__:
print base.__name__
break


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

class B(A):
def __init__(self):
A.__init__(self)

sys.settrace(mytrace)
B()

This will output:

B
B

whereas I'm shooting for:

B
A

Gabriel Genellina

unread,
Jul 16, 2007, 4:37:40 AM7/16/07
to pytho...@python.org

If you don't mind post-processing the results, you can log the function
name and source module (from frame.f_code.co_name and co_filename) and
current line number (frame.f_lineno). Later, obtaining the class name from
those is a bit tricky (and not even the inspect module does it right), but
perhaps using the tokenizer module, watching for lines that contain
"class" <name> is enough.

--
Gabriel Genellina

Erik Jones

unread,
Jul 16, 2007, 10:50:32 AM7/16/07
to Gabriel Genellina, pytho...@python.org


I was afraid of that. I used pretty much that tokenizer trick for a
unit test generator I wrote in php a while back and felt like that
was pretty clunky then.

Chris Mellon

unread,
Jul 16, 2007, 11:35:57 AM7/16/07
to pytho...@python.org


Hacky, but maybe this will work:

import sys
import inspect

def mytrace(frame, event, arg):
if event == 'call':
func_name = frame.f_code.co_name

klassOb = frame.f_locals['self'].__class__
for klass in inspect.getmro(klassOb):
cf = klass.__dict__.get(func_name)
if hasattr(cf, "func_code") and cf.func_code == frame.f_code:
print klass.__name__

Erik Jones

unread,
Jul 16, 2007, 12:25:49 PM7/16/07
to Chris Mellon, pytho...@python.org

Chris, that is absolutely perfect. Also, I don't think there is such
a thing as profiling code that isn't hacky ;)

0 new messages