Dynamically altering __init__
Kääriäinen Anssi
anssi.kaariainen at thl.fi
Thu Oct 13 07:25:52 EDT 2011
Hello all,
I am trying to alter the init method of a class by source to AST -> alter AST
-> AST back to code -> f = types.FunctionType(code, {}, '__init__') ->
mt = types.MethodType(f, None, Foo) -> Foo.__init__ = mt
I have two problems, first I haven't yet figured out how to make the AST back
to code, so that it will be accepted by types.FunctionType. Also, I can't make
the Foo.__init__ be callable with arguments. Here is an example without
using AST:
class Foo(object):
def __init__(self):
pass
src = """
def my_init_func(self, *args):
print "here"
"""
class Foo(object):
pass
import parser
import types
st = parser.suite(src)
dyn_func = parser.compilest(st)
f = types.FunctionType(dyn_func, {}, '__init__')
im = types.MethodType(f, None, Foo)
Foo()
Foo.__init__ = im
Foo(1, 2, 3)
The result is: TypeError: <module>() takes no arguments (4 given). I have
figured out that when I call f(), I am actually executing the src as is, not
the defined function in the src. But I can't figure out how to get a
reference to my_init_func.
You might be wondering why I am doing this. I am trying to rewrite this:
class Foo(object):
attrs = ['spam', 'eggs']
def __init__(self, *args):
for attname, val in izip(Foo.attrs, args):
setattr(self, attname, val)
into this:
...
def __init__(self, *args):
self.spam, self.eggs = args
This is done for performance reasons. There is about 2x difference when
creating 10000 objects. While it is a nice improvement, this is still mostly
just for learning purposes.
If you can help me it would be great. I am probably doing a lot of things
wrong, but there isn't too much information available about these shorts
of things. Link to example code would be perfect.
- Anssi Kääriäinen
More information about the Python-list
mailing list