Does python have an equivalent to Java Class.forName()?
Reflection in python is a lot easier and far more flexible than it is in Java.
I recommend reading this tutorial (on archive.org)
There's no direct function (that I know of) which takes a fully qualified class name and returns the class, however you have all the pieces needed to build that, and you can connect them together.
One bit of advice though: don't try to program in Java style when you're in python.
If you can explain what is it that you're trying to do, maybe we can help you find a more pythonic way of doing it.
Here's a function that does what you want:
def get_class( kls ):
parts = kls.split('.')
module = ".".join(parts[:-1])
m = __import__( module )
for comp in parts[1:]:
m = getattr(m, comp)
return m
You can use the return value of this function as if it were the class itself.
Here's a usage example:
>>> D = get_class("datetime.datetime")
>>> D
<type 'datetime.datetime'>
>>> D.now()
datetime.datetime(2009, 1, 17, 2, 15, 58, 883000)
>>> a = D( 2010, 4, 22 )
>>> a
datetime.datetime(2010, 4, 22, 0, 0)
>>>
How does that work?
We're using __import__
to import the module that holds the class, which required that we first extract the module name from the fully qualified name. Then we import the module:
m = __import__( module )
In this case, m
will only refer to the top level module,
For example, if your class lives in foo.baz
module, then m
will be the module foo
We can easily obtain a reference to foo.baz
using getattr( m, 'baz' )
To get from the top level module to the class, have to recursively use gettatr
on the parts of the class name
Say for example, if you class name is foo.baz.bar.Model
then we do this:
m = __import__( "foo.baz.bar" ) #m is package foo
m = getattr( m, "baz" ) #m is package baz
m = getattr( m, "bar" ) #m is module bar
m = getattr( m, "Model" ) #m is class Model
This is what's happening in this loop:
for comp in parts[1:]:
m = getattr(m, comp)
At the end of the loop, m
will be a reference to the class. This means that m
is actually the class itslef, you can do for instance:
a = m() #instantiate a new instance of the class
b = m( arg1, arg2 ) # pass arguments to the constructor
Dynamically instantiate object of the python class similar to PHP new $classname?
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'>
Initialise class object by name
If the class is in your scope:
get_class = lambda x: globals()[x]
If you need to get a class from a module, you can use getattr
:
import urllib2
handlerClass = getattr(urllib2, 'HTTPHandler')
Distinction between ClassObject.getClass,ClassName.class and Class.forName( ClassName )
Class.forName
loads and initializes the class. obj.getClass()
returns the class object loaded into permgen. If the class is loaded by the same classloader ==
has to return true. When you are see false
for == comparison it means that they are loaded by different classloaders.
C# equivalent of class.forName() in Java
You mean, like this?
typeof(YourClass).Name
To clarify, in .NET framework there's a class named Type
. This class has a property named Name
that retrieves the name of the class.
So, to retrieve the Type of a class in compile time you can use typeof
.
var typeName = typeof(YourClass).Name
If you doesn't know the type at runtime, you can retrieve it with the GetType()
method. This is common for all .NET objects.
Animal a = new Dog();
var typeName = a.GetType().Name;
Answer for Edit 1
You need to pass a Type
parameter
void X(Type classType)
{
var className = classType.Name;
Console.WriteLine(className);
}
And a call to X
should be like this
X(typeof(YourClass));
or
X(YourInstance.GetType());
Terrifying initial values - mutable types share same reference?
You have defined a class attribute instead of an instance attribute. Python is doing the right thing.
Instead of
class A(object):
v = [] # Class attribute, shared across all instances!
you need
class A(object):
def __init__(self): # Instance attribute, created anew for each new object
self.v = []
How to dynamically load a Python class
From the python documentation, here's the function you want:
def my_import(name):
components = name.split('.')
mod = __import__(components[0])
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
The reason a simple __import__
won't work is because any import of anything past the first dot in a package string is an attribute of the module you're importing. Thus, something like this won't work:
__import__('foo.bar.baz.qux')
You'd have to call the above function like so:
my_import('foo.bar.baz.qux')
Or in the case of your example:
klass = my_import('my_package.my_module.my_class')
some_object = klass()
EDIT: I was a bit off on this. What you're basically wanting to do is this:
from my_package.my_module import my_class
The above function is only necessary if you have a empty fromlist. Thus, the appropriate call would be like this:
mod = __import__('my_package.my_module', fromlist=['my_class'])
klass = getattr(mod, 'my_class')
Related Topics
How to Add Native Library to "Java.Library.Path" with Eclipse Launch (Instead of Overriding It)
How to Check If Internet Connection Is Present in Java
How to Load a Resource from Web-Inf Directory of a Web Archive
Java Split() Method Strips Empty Strings at the End
Failed to Install Android-Sdk: "Java.Lang.Noclassdeffounderror: Javax/Xml/Bind/Annotation/Xmlschema"
Android M Permissions: Onrequestpermissionsresult() Not Being Called
Android-Java- How to Sort a List of Objects by a Certain Value Within the Object
Gson - Convert from JSON to a Typed Arraylist<T>
How to Scroll a Scrollview Programmatically in Android
Jersey /* Servlet Mapping Causes 404 Error for Static Resources
Hibernate 5 :- Org.Hibernate.Mappingexception: Unknown Entity
How to Terminate Scanner When Input Is Complete
How to Add an Actionlistener Onto a Jbutton in Java
Java Heap Terminology: Young, Old and Permanent Generations