Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a class constructor to a python function

Suppose I have a class Foo, I want to define a function that receives the class constructor as a parameter:

def bar(class_name):
    local_class = None
    # TODO: if I call bar(Foo()), I want to get local_class = Foo()

How can I implement the function?

like image 404
beaver Avatar asked Sep 22 '15 05:09

beaver


2 Answers

The following bar function will work. Note, the first parameter will be a class itself and not the name of a class, so "class_name", which implies that it's a str, is misleading. args will be a tuple of args to initialize klass objects with, *-unpacked in the calls to klass. You said in a later comment that you wanted to "create multiple independent objects", all of the same class and initialized with the same args, so I've revised my answer to reflect that:

def bar(klass, *args):
    # Now you can create multiple independent objects of type klass,
    # all initialized with the same args
    obj1 = klass(*args)
    obj2 = klass(*args)
    # ...
    # do whatever you have in mind with the objs

Your "local_class" isn't a class at all, but rather an instance of klass, so that's a bad name; and anyway you want several of them.

Assuming Foo objects are initialized with three int arguments, and Baz objects with two strings, you can call bar like so:

bar(Foo, 1, 2, 3)
bar(Baz, 'Yo', 'bro')

etc.

Especially in a dynamically-typed language like Python, reasoning about code is more difficult when variables have misleading names.

like image 103
BrianO Avatar answered Oct 10 '22 04:10

BrianO


When can pass the classname as an argument to your function, and then call class_name(). E.g., if you also want to pass arguments.

class Foo:
    def __init__(self, arg1, arg2):
        pass

def bar1(class_name):
    args = ("val1", "val2")
    local_class = class_name(*args)

or

def bar2(class_name):
    kwargs = {'arg1':'val1','arg2':'val2'}
    local_class = class_name(**kwargs)

You can call the functions like:

one = bar1(Foo)
two = bar2(Foo)

If you really want to call the class from a string read this post. I would suggest you use @Evan Fosmark's solution because use of eval and globals should be avoided

like image 37
MartyB Avatar answered Oct 10 '22 03:10

MartyB