0

How to instantiated a class if its name is given as a string variable (i.e. dynamically instantiate object of the class). Or alternatively, how does the following PHP 5.3+ code

<?php

namespace Foo;

class Bar {};

$classname = 'Foo\Bar';
$bar = new $classname();

can be spelled in python?

Also see

Does python have an equivalent to Java Class.forName()?

Community
  • 1
  • 1
Yauhen Yakimovich
  • 13,635
  • 8
  • 60
  • 67

2 Answers2

1

foo.py

class Bar(object):
    pass

test.py

from importlib import import_module

module = import_module('foo')
BarCls = getattr(module, 'Bar')
bar = BarCls()
Yauhen Yakimovich
  • 13,635
  • 8
  • 60
  • 67
1

Here is some code I use to go from a full class path (e.g. foo.bar.baz.TheClass) to the class itself:

def get_class(class_path):
    module_path, class_name = class_path.rsplit(".", 1)

    try:
        module = __import__(module_path, fromlist=[class_name])
    except ImportError:
        raise ValueError("Module '%s' could not be imported" % (module_path,))

    try:
        cls = getattr(module, class_name)
    except AttributeError:
        raise ValueError("Module '%s' has no class '%s'" % (module_path, class_name,))

    return cls

Usage:

>>> get_class('twisted.internet.nonexistant.Deferred')

Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    get_class('twisted.internet.nonexistant.Deferred')
  File "<pyshell#1>", line 7, in get_class
    raise ValueError("Module '%s' could not be imported" % (module_path,))
ValueError: Module 'twisted.internet.nonexistant' could not be imported
>>> get_class('twisted.internet.defer.NoClass')

Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    get_class('twisted.internet.defer.NoClass')
  File "<pyshell#13>", line 12, in get_class
    raise ValueError("Module '%s' has no class '%s'" % (module_path, class_name,))
ValueError: Module 'twisted.internet.defer' has no class 'NoClass'
>>> get_class('twisted.internet.defer.Deferred')
<class twisted.internet.defer.Deferred at 0x02B25DE0>

Note that this doesn't necessarily return a class, it just returns the attribute of the imported module:

>>> get_class('twisted.internet')
<module 'twisted.internet' from 'C:\Python26\lib\site-packages\twisted\internet\__init__.pyc'>
Claudiu
  • 224,032
  • 165
  • 485
  • 680