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

Create a class at run-time

8 views
Skip to first unread message

Michel

unread,
Mar 25, 2010, 6:00:35 PM3/25/10
to
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?
I looked at types.MethodType but it needs an instance to bind the
method and a function object.
Should I define __new__ to bind the method during instantiation?

Hope this makes sense,

Michel.

Michiel Overtoom

unread,
Mar 25, 2010, 6:18:17 PM3/25/10
to pytho...@python.org
On 2010-03-25 23:00, Michel wrote:

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

Maybe this snippet is of any help?

import functools

class Template(object):
pass

def printmyname(self):
print self.name

t=Template()
t.name="Pete"
t.printmyname=functools.partial(printmyname,t)

u=Template()
u.name="Mary"
u.printmyname=functools.partial(printmyname,u)

t.printmyname()
u.printmyname()

Greetings,


--
"The ability of the OSS process to collect and harness
the collective IQ of thousands of individuals across
the Internet is simply amazing." - Vinod Valloppillil
http://www.catb.org/~esr/halloween/halloween4.html

Patrick Maupin

unread,
Mar 25, 2010, 6:34:32 PM3/25/10
to
On Mar 25, 5:00 pm, Michel <michel.metz...@gmail.com> 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:

Well, you should just fill your empty dict with function definitions,
BEFORE you build the class. That's easiest. Also, you can just use
type:

def foo(*whatever):
print foo

bar = type('MyDynamicClass', (object,), dict(foo=foo))

HTH,
Pat

I V

unread,
Mar 25, 2010, 9:53:04 PM3/25/10
to
On Thu, 25 Mar 2010 15:00:35 -0700, Michel wrote:
> 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:

I'm not entirely sure what you mean by binding methods to the instance.
Do you mean you need to dynamically add methods to a specific instance?
Or that you need to add methods to a class, such that they can be invoked
on specific instances? For the latter, just do:

TestClass.test_foo = test_foo

For the former, try:

tc = TestClass()
tc.test_foo = types.MethodType(test_foo, tc)

Michel

unread,
Mar 26, 2010, 11:00:57 AM3/26/10
to
Well, I don't have the reference to the instance. The class is
actually instantiated later by a the unittest library.

Michel

unread,
Mar 26, 2010, 11:54:11 AM3/26/10
to
I want to add a method to a class such that it can be invoked on
specifics instances.
You solution works (as well as Patrick's one), thanks !
I still have a question though. If I print the type of the self object
I get when my method is
called, I get "<class 'test.TestClass'>". I guess this is because the
method is defined as a class method.
This is ok in my case, but just out of curiosity, what should I do to
change this method to an instance method?

Thanks for your help,

Michel.

Peter Otten

unread,
Mar 26, 2010, 1:29:23 PM3/26/10
to pytho...@python.org
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

Michel

unread,
Mar 26, 2010, 2:41:21 PM3/26/10
to
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.

Peter Otten

unread,
Mar 26, 2010, 3:16:28 PM3/26/10
to
Michel wrote:

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

Steve Holden

unread,
Mar 26, 2010, 3:19:44 PM3/26/10
to pytho...@python.org
Yes, it's just that MyClass is an old-style class (its type is <type
'classobj'>) whereas MyDynClass is a new-style class (its type is <type
'type'>, because it inherits from object).

It's as though you had written

class MyClass:
...

class MyDynClass(object):
...

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
See PyCon Talks from Atlanta 2010 http://pycon.blip.tv/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS: http://holdenweb.eventbrite.com/

I V

unread,
Mar 26, 2010, 4:46:04 PM3/26/10
to
On Fri, 26 Mar 2010 08:54:11 -0700, Michel wrote:

> I want to add a method to a class such that it can be invoked on
> specifics instances.
> You solution works (as well as Patrick's one), thanks ! I still have a
> question though. If I print the type of the self object I get when my
> method is
> called, I get "<class 'test.TestClass'>". I guess this is because the
> method is defined as a class method.
> This is ok in my case, but just out of curiosity, what should I do to
> change this method to an instance method?

It already is an instance method. When you create a TestClass instance,
the type of that instance is TestClass (the type of TestClass itself is
"type").

0 new messages