ActiveState Code

Recipe 285262: Create objects from variable class names


I sometimes want to create objects from various classes based on some condition (without using eval()). For example when parsing X(HT)ML files I want to handle some tags using specific classes. It is actually quite easy but I had a hard time finding out how to do that, no doubt due to my limited knowledge of python, so here's a simple example.

Edit: See also <a href="http://www.faqts.com/knowledge_base/view.phtml/aid/2635/fid/242">http://www.faqts.com/knowledge_base/view.phtml/aid/2635/fid/242</a>

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class A(object):
	def __init__(self):
		print 'This is A'
	def foo(self):
		print "foo"

class B(object):
	def __init__(self):
		print 'This is B'
	def foo(self):
		print "bar"

def getObject(cond):
	if cond:
		classname = 'A'
	else:
		classname = 'B'
	object = globals()[classname]
	return object()

myobject = getObject(1)
myobject.foo()
print dir(myobject)

print

a = A()
a.foo()
print dir(a)

print

myobject = getObject(0)
myobject.foo()
print dir(myobject)

print

b = B()
b.foo()
print dir(b)

Discussion

Produces this output:

This is A foo ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'foo']

This is A foo ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'foo']

This is B bar ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'foo']

This is B bar ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'foo']

As you can see, and as far as I can tell, the results are identical.

Comments

  1. 1. At 3:49 p.m. on 10 jun 2004, Hamish Lawson said:

    You can specify the class directly rather than by name. Python classes can be passed around, so you can refer them to directly rather than by name:

    def getObject(cond):
        if cond:
            cls = A
        else:
            cls = B
        return cls()
    

    If you need a multiway decision you can use a dictionary that has the candidate classes as its values.

  2. 2. At 7:29 a.m. on 23 jun 2004, Peter van Kampen (the author) said:

    This assumes you know the names of the classes in advance. I needed to be able to create objects from classnames that were only known at runtime. The example isn't very good I guess but I wanted to provide a simple example.

  3. 3. At 6:40 a.m. on 3 dec 2004, Harry Fuecks said:

    Call object method from string. Had a situation where I needed this for an XML-RPC server to dispatch calls. May be a smarter way to do it but couldn't find it;

    class Dispatcher:
        def _dispatch(self, method, params):
            # XML-RPC request method: MyClass.someMethod
            handler, method = string.split(method,'.',1)
    
            # Perhaps dynamically __import__() here...
    
            # Get the class
            clas = globals()[handler]
    
            # Get the method in the class
            func = class.__dict__[method]
    
            # Create the object
            obj = clas()
    
            # Shift the obj instance into the start of the params
            params.insert(0,obj)
    
            # Call the function...
            apply(func,params)
    

Sign in to comment