Using Variables for Class Names in Python?
Asked Answered
D

6

49

I want to know how to use variables for objects and function names in Python. In PHP, you can do this:

$className = "MyClass";

$newObject = new $className();

How do you do this sort of thing in Python? Or, am I totally not appreciating some fundamental difference with Python, and if so, what is it?

Dink answered 21/10, 2008 at 21:24 Comment(7)
I'd be interested to hear why you need to do this -- I think there might be a more Pythonic way which doesn't require variable class names.Marinamarinade
"am I totally not appreciating some fundamental difference with Python, and if so, what is it?" Possibly. Why do you use code like the above example? Please provide a bigger example that provides some context.Allman
Interesting, but I agree with TimB, I'd like to hear the use case for this.Densitometer
there are no variables in python, just names.Judyjudye
In one recent case, I implemented two different subclasses of a class. They had similar different implementations for the same general work, and they had roughly the same API. I guess that's a strategy pattern? Anyway, I wanted to dynamically use one or the other depending on context.Dink
strategy = dict(strategy1=Class1, stategy2=Class2). stragey["strategy1"]()Corum
I had a similar case where the name of the class to instantiate had to be found in a config file. The use of [eval] of @Marinamarinade was the solution for me.Adman
I
30

In Python,

className = MyClass
newObject = className()

The first line makes the variable className refer to the same thing as MyClass. Then the next line calls the MyClass constructor through the className variable.

As a concrete example:

>>> className = list
>>> newObject = className()
>>> newObject
[]

(In Python, list is the constructor for the list class.)

The difference is that in PHP, you represent the name of the class you want to refer to as a string, while in Python you can reference the same class directly. If you must use a string (for example if the name of the class is created dynamically), then you will need to use other techniques.

Indices answered 21/10, 2008 at 21:26 Comment(5)
downvoted, because your solution does not match the one in the question. What he is looking for is instantiation of a class with a string.Navarra
Please keep to PEP8. Using mixedCase names feels somewhat against the values SO stands for.Austere
Agree with the first comment, this doesn't work for a class name stored in a variblePeristalsis
It works for the OP, that is why he has accepted this answer @Peristalsis . Also it works for me.Justice
@reggie, thought he asked about a string,I think may guy who made question also solve problem with Greg Hewgill solution. Because, all class we wanna use must be existed already, he can import them to a as names to use, not a random string!Weapon
F
69

Assuming that some_module has a class named "class_name":

import some_module
klass = getattr(some_module, "class_name")
some_object = klass()

I should note that you should be careful here: turning strings into code can be dangerous if the string came from the user, so you should keep security in mind in this situation. :)

One other method (assuming that we still are using "class_name"):

class_lookup = { 'class_name' : class_name }
some_object = class_lookup['class_name']()  #call the object once we've pulled it out of the dict

The latter method is probably the most secure way of doing this, so it's probably what you should use if at all possible.

Foiled answered 21/10, 2008 at 21:33 Comment(2)
Very nice, I am creating a handle for dynamic classes and dynamic fields. I did classes = {'class1': Class1, 'class2': Class2,...}. Now I can get the object with myob = classes['<class_name'].objects.get(id=<obj_id>).Gesner
Great, simple trick. Was bugging 2 hours before I found this. Thanks.Chessy
I
30

In Python,

className = MyClass
newObject = className()

The first line makes the variable className refer to the same thing as MyClass. Then the next line calls the MyClass constructor through the className variable.

As a concrete example:

>>> className = list
>>> newObject = className()
>>> newObject
[]

(In Python, list is the constructor for the list class.)

The difference is that in PHP, you represent the name of the class you want to refer to as a string, while in Python you can reference the same class directly. If you must use a string (for example if the name of the class is created dynamically), then you will need to use other techniques.

Indices answered 21/10, 2008 at 21:26 Comment(5)
downvoted, because your solution does not match the one in the question. What he is looking for is instantiation of a class with a string.Navarra
Please keep to PEP8. Using mixedCase names feels somewhat against the values SO stands for.Austere
Agree with the first comment, this doesn't work for a class name stored in a variblePeristalsis
It works for the OP, that is why he has accepted this answer @Peristalsis . Also it works for me.Justice
@reggie, thought he asked about a string,I think may guy who made question also solve problem with Greg Hewgill solution. Because, all class we wanna use must be existed already, he can import them to a as names to use, not a random string!Weapon
F
25

If you need to create a dynamic class in Python (i.e. one whose name is a variable) you can use type() which takes 3 params: name, bases, attrs

>>> class_name = 'MyClass'
>>> klass = type(class_name, (object,), {'msg': 'foobarbaz'})

<class '__main__.MyClass'>

>>> inst = klass()
>>> inst.msg
foobarbaz
  • Note however, that this does not 'instantiate' the object (i.e. does not call constructors etc. It creates a new(!) class with the same name.
Farmland answered 20/5, 2010 at 15:14 Comment(0)
M
8

If you have this:

class MyClass:
    def __init__(self):
        print "MyClass"

Then you usually do this:

>>> x = MyClass()
MyClass

But you could also do this, which is what I think you're asking:

>>> a = "MyClass"
>>> y = eval(a)()
MyClass

But, be very careful about where you get the string that you use "eval()" on -- if it's come from the user, you're essentially creating an enormous security hole.

Update: Using type() as shown in coleifer's answer is far superior to this solution.

Marinamarinade answered 21/10, 2008 at 21:32 Comment(2)
OMG, no! The eval function is evil. Do not use it.Norrisnorrv
@TimB, I think this should be the best answer if it is up to me.Gylys
L
1

I use:

newObject = globals()[className]()
Lazaro answered 24/1, 2020 at 16:39 Comment(0)
S
0

I prefer using dictionary to store the class to string mapping.

>>> class AB:
...   def __init__(self, tt):
...     print(tt, "from class AB")
... 
>>> class BC:
...   def __init__(self, tt):
...     print(tt, "from class BC")
... 
>>> x = { "ab": AB, "bc": BC}
>>> x
{'ab': <class '__main__.AB'>, 'bc': <class '__main__.BC'>}
>>> 
>>> x['ab']('hello')
hello from class AB
<__main__.AB object at 0x10dd14b20>
>>> x['bc']('hello')
hello from class BC
<__main__.BC object at 0x10eb33dc0>
Sanies answered 12/4, 2022 at 4:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.