Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Reference to a class from a string?

Tags:

python

How to use a string containing a class name to reference a class itself?
See this (not working) exemple...

class WrapperClass:
    def display_var(self):
        #FIXME: self.__class_name__.__name__ is a string
        print self.__class__.__name__.the_var

class SomeSubClass(WrapperClass):
    var = "abc"

class AnotherSubClass(WrapperClass):
    var = "def"

And an obvious error message:

>>> b = SomeSubClass()
>>> b.display_var()
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 4, in display_var
AttributeError: 'str' object has no attribute 'the_var'
>>> 

Thanks!

like image 296
Orphee Avatar asked Dec 09 '22 21:12

Orphee


2 Answers

How to use a string containing a class name to reference a class itself?

Classes aren't special, they're just values contained in variables. If you've said:

class X(object): pass

in global scope, then the variable ‘X’ will be a reference to the class object.

You can get the current script/module's global variables as a dictionary using ‘globals()’, so:

classobj= globals()[self.__class__.__name__]
print classobj.var

(locals() is also available for local variables; between them you shouldn't ever need to use the awful eval() to access variables.)

However as David notes, self.__class__ is already the classobj, so there's no need to go running about fetching it from the global variables by name; self.__class__.var is fine. Although really:

print self.var

would be the usual simple way to do it. Class members are available as members of their instances, as long as the instance doesn't overwrite the name with something else.

like image 104
bobince Avatar answered Dec 12 '22 09:12

bobince


Depending on where you get this string, any general method may be insecure (one such method is to simply use eval(string). The best method is to define a dict mapping names to classes:

class WrapperClass:
    def display_var(self):
        #FIXME: self.__class_name__.__name__ is a string
        print d[self.__class__.__name__].the_var

class SomeSubClass(WrapperClass):
    the_var = "abc"

class AnotherSubClass(WrapperClass):
    the_var = "def"

d = {'WrapperClass': WrapperClass, 'SomeSubClass': SomeSubClass, 'AnotherSubClass': AnotherSubClass}
AnotherSubClass().display_var()
# prints 'def'
like image 35
Devin Jeanpierre Avatar answered Dec 12 '22 09:12

Devin Jeanpierre