Create a class at run-time
Peter Otten
__peter__ at web.de
Fri Mar 26 15:16:28 EDT 2010
Michel wrote:
> 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.
In Python 2.x there are "classic" and "newstyle" classes. In practice the
main differences are that classic classes are more likely to call
__getattr__() and that only newstyle classes support properties correctly.
By inheriting from object you make MyDynClass a newstyle class:
>>> classic = types.ClassType("A", (), {})
>>> newstyle = types.ClassType("A", (object,), {})
>>> type(classic()), type(classic)
(<type 'instance'>, <type 'classobj'>)
>>> type(newstyle()), type(newstyle)
(<class '__main__.A'>, <type 'type'>)
Classic classes exist for backwards compatibility and because most
programmers are too lazy to have their classes inherit from object when the
difference doesn't matter. When you create a class dynamically I recommend
that you use the type() builtin instead of types.ClassType(). This will
always create a newstyle class -- even when you don't inherit from object
explicitly:
>>> type(type("A", (), {}))
<type 'type'>
>>> type("A", (), {}).__bases__
(<type 'object'>,)
Peter
More information about the Python-list
mailing list