Create a class at run-time

Michel michel.metzger at gmail.com
Fri Mar 26 14:41:21 EDT 2010


Thanks Peter.

I searched a little bit more and wrote the following example:

------------------------------------
import types

class MyClass:

    def test_toto(self):
        print type(self)
        print self.name

def test_toto(self):
    print type(self)
    print self.name

MyDynClass = types.ClassType("MyDynClass", (object, ), {})
MyDynClass.__module__ = "test.complex.hierarchy"
MyDynClass.test_toto = test_toto

t1 = MyDynClass()
t2 = MyDynClass()

t1.name = "Marcel"
t2.name = "Oscar"

t1.test_toto()
t2.test_toto()

c1 = MyClass()
c1.name = "Raoul"
c1.test_toto()
--------------------------------

the output is:

<class 'test.complex.hierarchy.MyDynClass'>
Marcel
<class 'test.complex.hierarchy.MyDynClass'>
Oscar
<type 'instance'>
Raoul

I'm wondering why the type of the self parameter is not 'instance' in
the calls
t1.test_toto() and t2.test_toto()

The rest of the behavior is correct though, so I guess it's just
internal Python stuff.

Thanks for your help,

Michel.

On Mar 26, 1:29 pm, Peter Otten <__pete... at web.de> wrote:
> Michel wrote:
> > Hi everyone,
>
> > I'm trying to dynamically create a class. What I need is to define a
> > class, add methods to it and later instantiate this class. Methods
> > need to be bound to the instance though, and that's my problem. Here
> > is what I have so far:
>
> > method_template = "def test_foo(self):\
> >     #actual test_foo\
> >     pass"
> > exec method_template
>
> > TestClass = types.ClassType("MyTestClass", (unittest.TestCase, ), {})
> > TestClass.__module__ = "test"
>
> > now what to do next?
>
> Just assign it:
>
> >>> import unittest
> >>> class MyTestClass(unittest.TestCase): pass
> ...
> >>> def test_foo(self):
>
> ...     self.assertEquals(1, 2)
> ...>>> MyTestClass.test_foo = test_foo # <----
> >>> unittest.main()
>
> F
> ======================================================================
> FAIL: test_foo (__main__.MyTestClass)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "<stdin>", line 2, in test_foo
> AssertionError: 1 != 2
>
> ----------------------------------------------------------------------
> Ran 1 test in 0.000s
>
> FAILED (failures=1)
>
> If you don't know the method name beforehand use
>
> setattr(MyTestClass, method_name, method), e. g:
>
> >>> import unittest
> >>> class MyTestClass(unittest.TestCase): pass
>
> ...                                          >>> def make_method(n):
>
> ...     def test(self): self.assertEquals(2, n)
> ...     return test                            
> ...>>> for i in range(3):
>
> ...     setattr(MyTestClass, "test_%d" % i, make_method(i))
> ...>>> unittest.main()
>
> FF.
> ======================================================================
> FAIL: test_0 (__main__.MyTestClass)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "<stdin>", line 2, in test
> AssertionError: 2 != 0
>
> ======================================================================
> FAIL: test_1 (__main__.MyTestClass)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "<stdin>", line 2, in test
> AssertionError: 2 != 1
>
> ----------------------------------------------------------------------
> Ran 3 tests in 0.000s
>
> FAILED (failures=2)
>
> Peter




More information about the Python-list mailing list