2

I have a class, trying to instantiate another class, based off of a variable name passed to it. It is complaining that 'str' object is not callable. What is the proper way to do this?

def MyClass:
    def __init__(self, otherName):
        self.other = otherName()

EDIT: Here is the entirety of my code, is there anything I should do differently? Is eval evil in Python?

#!/usr/bin/python                                                                                                                                                                      

class Model:
    def get_post(self, id):
        # Would query database, perhaps                                                                                                                                                
        return {"title": "Python :: Test Page", "body": "Test page using Python!"}

class Controller:
    def __init__(self, viewName):
        self.model = Model()
        self.view = viewName()

    def main(self):
        post = self.model.get_post(1)
        self.view.display(post)

class View:
    def header(self, item):
        print "Content-type: text/html\r\n\r\n"
        print "<html>"
        print "<head>"
        print "<title>%(title)s</title>" % item
        print "</head>"
        print "<body>"

    def footer(self, item):
        print "</body>"
        print "</html>"

class Blog(View):
    def display(self,item):
 View.header(self,item)
 print "<p>%(body)s</p>" % item
 View.footer(self,item)

c = Controller(Blog)
c.main()
Josh
  • 12,448
  • 10
  • 74
  • 118
  • 1
    The proper way to do this is to search on SO for this question, which has been asked numerous times before. – S.Lott Dec 30 '10 at 22:13
  • This might be relevant: http://stackoverflow.com/questions/553784/can-you-use-a-string-to-instantiate-a-class-in-python – wkl Dec 30 '10 at 22:13
  • possible duplicate of [Python: Reference to a class from a string?](http://stackoverflow.com/questions/734970/python-reference-to-a-class-from-a-string) – S.Lott Dec 30 '10 at 22:13
  • [This answer](http://stackoverflow.com/questions/452969/does-python-have-an-equivalent-to-java-class-forname/452971#452971) is probably what you're looking for... – Cameron Dec 30 '10 at 22:17
  • Don't you think showing us how you're trying to instantiate MyClass() would be important here? And also __init() isn't a constructor. – Falmarri Dec 30 '10 at 22:17
  • @Falmarri I forgot the trailing __, and I'm simply doing: m = myClass("Blog") – Josh Dec 30 '10 at 22:18
  • 1
    Uh... your code as posted works (once I fix the indentation in the Blog class), and I don't see where you are using, nor propose to use, `eval`. – Karl Knechtel Dec 30 '10 at 23:10
  • "is eval evil in Python?" No. It's usually a waste of keystrokes. Please read @Greg Hewgill's answer. You don't need `eval`. So don't waste time typing it, the ()'s and the "'s. – S.Lott Dec 30 '10 at 23:49

3 Answers3

9

You can do this without using strings at all. You can refer to classes in Python by name, and pass them around just like any other object. So, using your definition of MyClass above, instead of doing:

c = Controller("Blog")

you can use simply:

c = Controller(Blog)

Using eval() for something like this is definitely not recommended.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
0

You should be able to get to your class through the dict that the locals() function returns. Here is a simple class,

class ClassA:
    def __init__(self, word):
        self.word = word

    def __str__(self):
        return "Class A word is '%s'" % self.word

I can create this class from a string of its name, and call it normally,

>>> myclass = locals()['ClassA']('wibble')
>>> print myclass
Class A word is 'wibble'
aid
  • 136
  • 3
-1

If you really would like to pass the parameter as a string, you could use eval().

class MyClass: 
    def __init(self, otherName): 
        self.other = eval(otherName)()
Felix
  • 35,354
  • 13
  • 96
  • 143
  • 5
    Using `eval` should be a last resort. – Falmarri Dec 30 '10 at 22:24
  • `eval` generally leads to wierd unreproducable bugs and should be avoided in nearly all cases. Python gives great flexibility to do kooky metaprogramming without resorting to literal evaluation of constructed code. – richo Dec 30 '10 at 22:42