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

E

Erik Jones

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®
(e-mail address removed)
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
 
M

Michele Simionato

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
 
E

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.

Erik Jones

Software Developer | Emma®
(e-mail address removed)
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
 
M

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__
 
E

Erik Jones

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__

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

Software Developer | Emma®
(e-mail address removed)
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
 
E

Erik Jones

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



Erik Jones

Software Developer | Emma®
(e-mail address removed)
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
 
G

Gabriel Genellina

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

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.
 
E

Erik Jones

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

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.


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.

Erik Jones

Software Developer | Emma®
(e-mail address removed)
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
 
C

Chris Mellon

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

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.


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.


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__


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

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

sys.settrace(mytrace)
B()
 
E

Erik Jones

En Mon, 16 Jul 2007 03:56:18 -0300, Erik Jones <[email protected]>
escribió:

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

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.


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.


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__


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

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

sys.settrace(mytrace)
B()

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

Erik Jones

Software Developer | Emma®
(e-mail address removed)
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
 

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
474,438
Messages
2,571,699
Members
48,796
Latest member
Greg L.
Top