Getting an object by name - python

Is it possible to create an instance of a class by giving its name, e.g.:
instance = "TestXYZ"()
Assuming that TestXYZ is imported by a class that imports the code above and TestXYZ is defined as:
class TestXYZ(object):
...

Yes, it is possible. The mechanics depend on how you import the class:
>>> globals()["TestXYZ"]()
<__main__.TestXYZ object at 0x10f491090>
or
>>> getattr(sys.modules["test_module"], "TestXYZ")()
<test_module.TestXYZ object at 0x10cf22090>

You can get a reference to an object from current namespace using:
klass = globals()['TestXYZ']
Then you can create an instance of the class:
instance = klass()

I am not sure why do you want to do this, but instead of using globals() I'd suggest you to create a dictionary here:
class Foo:
pass
d = {'Foo':Foo}
ins = d['Foo']()
Or move the class to some other module:
import some_module
ins = getattr(some_module, 'Foo')()

Related

python: call a class from a script in a different directory and get function

I have a script that I am currently working on, named exp1.py and it's located in
/project/exp1.py
In this script, I am trying to call a function named computelikelihood(), which is inside the class Class(), which is in script method.py, in a different directory:
/project/methods/c_CLASS/method.py
So, in my code in exp1.py, I do this:
import sys
sys.path.append('/project/methods/c_CLASS/')
Which gets me to the folder where method.py is located, but when I want to call the Class() from the method.py, so that I get the function computelikelihood(), that I actually want, I get error. I try this:
from method import Class
from Class import computelikelihood
But I get ImportError: No module named Class. Can anyone help?
EDIT
This is how the __init__ of my Class looks like:
class Class:
def __init__(self,e2wl,w2el,label_set):
self.e2wl = e2wl
self.w2el = w2el
self.workers = self.w2el.keys()
self.examples = self.e2wl.keys()
self.label_set = label_set
Since you are trying to use a method from a Class, you should do so via the class. Do not import the function alone as it isn't intended to be used as such:
from method import Class
Class.computelikelihood()
However, this only works if computelikelihood is a static/class method:
class Class:
#classmethod
def computelikelihood(cls):
...
# or
#staticmethod
def computelikelihood():
...
If it's an instance method:
class Class:
def computelikelihood(self):
...
You'll need to first instantiate an object of class Class:
from method import Class
classObject = Class()
classObject.computelikelihood()

How to know if a variable is imported in python2.7?

I want to list variables "defined" in a module. And then I found there is no way to distinct variables defined in the module and variables imported from other modules. Is there any way to know if a variable is imported?
I KNOW inspect.getmembers and inspect.getmodule and dir but my concern is variable, not function or class definition.
AND I KNOW I COULD IMPORT MODULE RATHER THAN IMPORT VARIABLE FROM MODULE.
I just want to know is there a way or not :).
a.py, define a class
class A(object):
pass
b.py, define a instance using class A
from a import A
ins_b = A()
c.py, define another instance using class A and
from a import A
from b import ins_b
ins_c = A()
I want to list variables like this:
["b.ins_b", "c.ins_c"]
but actually I could do is :
{
<a.A instance at pos1>: ["b.ins_b", "c.ins_b"],
<a.A instance at pos2>: ["c.ins_c"],
}
OK. Thanks to #juanpa.arrivillaga I know it is impossible to do this.
And I just change the problem: how to know "the module which object is created" and "the attr name which the object is assigned".
I try to find something like "metaclass", maybe "metamodule" but I find it changes many behaviors which I do not need.
So according to "How to use inspect to get the caller's info from callee in Python?" and "Retrieve module object from stack frame", I do some trick to realize my idea.
import inspect
import re
attr_r = re.compile(u"\s*([^\s=]+)\s*=")
class A(object):
def __init__(self):
pre_frame = inspect.currentframe().f_back
frame_info = inspect.getframeinfo(pre_frame)
self.init_module_name = inspect.getmodule(pre_frame).__name__
self.init_attr_name = ""
if len(frame_info[3]) > 0:
line = frame_info[3][0]
m = attr_r.match(line)
if m:
self.init_attr_name = m.group(1)
the method to get attr name is trick but work for me.
# init_module_name == "a"
a = A()
print a.init_module_name, a.init_attr_name
# init_module_name == "a"
a = b = A()
print a.init_module_name, a.init_attr_name
# init_module_name == ""
a = \
A()
print a.init_module_name, a.init_attr_name

Instantiate Python subclasses from different directories

I have some modules that are in different directories. How can I instantiate classes in these modules only if the classes are subclasses of ParentClass? Essentially, I am trying something like this below and want to know how I can implement child_class_name
from importlib.machinery import SourceFileLoader
from parent_class import ParentClass
instances = []
script_path1 = r'/some/different/directory/some_child.py'
script_path2 = r'/some/different/directory/another_child.py'
for script_path in [script_path1, script_path2]:
module = SourceFileLoader('module', script_path).load_module()
child_class_name = "If a class in this module is a subclass of ParentClass"
ChildClass = getattr(module, child_class_name)
instances.append(ChildClass())
This should work with this comprehension list:
childclasses = [obj for obj in vars(module).values()
if isinstance(obj,type) and issubclass(obj,ParentClass)]
vars(module).values() returns all objects living in the module.
Then you can filter the subclasses with issubclass(obj,ParentClass).
(isinstance will just help to filter class objects.)
childclasses is a list of classes that you can instantiate directly, without using getattr :
for ChildClass in childclasses:
instances.append(ChildClass())
EDIT :
To avoid ParentClass you can convert the list to a set, and remove it if it exists :
childclasses = set([obj for obj in vars(module).values()
if isinstance(obj,type) and issubclass(obj,ParentClass)])
if ParentClass in childclasses:
childclasses.remove(ParentClass)
or add another test in the comprehension :
childclasses = [obj for obj in vars(module).values()
if isinstance(obj,type) and
issubclass(obj,ParentClass)and
obj is not ParentClass ]

How to give a class a referencable string name?

The scenerio is I'm using an arg parser to get a command line argument auth_application.
auth_application command can have many values, for example:
cheese
eggs
noodles
pizza
These values are related to a programmable class.
I'd like a way to name the class, possible using a decorator.
So I can say
if auth_application is Cheese.__name__:
return Cheese()
Currently I maintain a tuple of auth_application names and have to expose that to my arg parser class as well as import the classes I need.
Anyways to make this better? Is there a decorator for classes to name them?
I'm looking for a python 2.7 solution, but a python 3 solution might be useful to know.
Easy peasy.
class command(object):
map = {}
def __init__(self, commandname):
self.name = commandname
def __call__(self, cls):
command.map[self.name] = cls
return cls
class NullCommand(object):
pass
#command('cheese')
class Cheese(object):
pass
#command('eggs')
class Eggs(object):
pass
def func(auth_application):
return command.map.get(auth_application, command.NullCommand)()
You can just keep a sinlge list of all of your "allowed classes" and iterate over that to find the class being referred to from the command line.
allow_classes = [Cheese,Eggs,Noodles,Pizza]
for cls in allow_classes:
if auth_application.lower() is cls.__name__.lower():
return cls()
Absolutely you can! You need to understand class attributes.
class NamedClass(object):
name = "Default"
class Cheese(NamedClass):
name = "Cheese"
print(Cheese.name)
> Cheese
You can use the standard Inspect Library to get the real class names, without having to augment your classes with any extra data - and this works for any class, in any module - even if you don't have the source code.
For instance - to list all the classes defined in mymodule :
import mymodule
import inspect
for name, obj in inspect.getmembers(mymodule, inspect.isclass):
print name
the obj variable is a real class object - which you can use to declare an instance, access class methods etc.
To get the definition of a class by it's name string - you can write a simple search function :
import mymodule
import inspect
def find_class(name):
"""Find a named class in mymodule"""
for this_name, _cls_ in inspect.getmembers(mymodule, inspect.isclass):
if this_name = name:
return _cls_
return None
....
# Create an instance of the class named in auth_application
find_class(auth_application)(args, kwargs)
NB: Code snippets not tested

How to pickle an instance of a class which is written inside a function?

Suppose I have this snippet inside a module
def func(params):
class MyClass(object):
pass
How can I pickle an instance of the class MyClass ?
You can't, because picklable object's class definitions must reside in an imported module's scope. Just put your class inside module scope and you are good to go.
That said, in Python there is very little that can't be achieved with a bit of hacking the insides of the machinery (sys.modules in this case), but I wouldn't recommend that.
The MyClass definition is local variable for the func function. You cannot directly create an instance of it, but you can map it's functions to a new class, and then to use the new class as it is the original one. Here's an example:
def func(params):
class MyClass(object):
some_param = 100
def __init__(self, *args):
print "args:", args
def blabla(self):
self.x = 123
print self.some_param
def getme(self):
print self.x
func.func_code is the code of the func function, and func.func_code.co_consts[2] contains the bytecode of the MyClass definition:
In : func.func_code.co_consts
Out:
(None,
'MyClass',
<code object MyClass at 0x164dcb0, file "<ipython-input-35-f53bebe124be>", line 2>)
So we need the bytecode for the MyClass functions:
In : eval(func.func_code.co_consts[2])
Out:
{'blabla': <function blabla at 0x24689b0>,
'__module__': '__main__',
'getme': <function getme at 0x2468938>,
'some_param': 100,
'__init__': <function __init__ at 0x219e398>}
And finally we create a new class with metaclass, that assigns the MyClass functions to the new class:
def map_functions(name, bases, dict):
dict.update(eval(func.func_code.co_consts[2]))
return type(name, bases, dict)
class NewMyClass(object):
__metaclass__ = map_functions
n = NewMyClass(1, 2, 3, 4, 5)
>> args: (1, 2, 3, 4, 5)
n.blabla()
>> 100
n.getme()
>> 123
This is somewhat tough to do because the way Pickle does with objects from user defined classes by default is to create a new instance of the class - using the object's __class__.__name__ attribute to retrieve its type in the object's original module. Which means: pickling and unpickling only works (by default) for classes that have well defined names in the module they are defined.
When one defines a class inside a function, usulay there won't be a module level (i.e. global) variable holding the name of each class that was created inside the function.
The behavior for pickle and npickle can be customized through the __getstate__ and __setstate__ methods on the class - check the docs - but even them, doing it right for dynamic class can be tricky , but I managed to create a working implementation of it for another S.O. question - -check my answer here:
Pickle a dynamically parameterized sub-class
You can work around the pickle requirement that class definitions be importable by including the class definition as a string in the data pickled for the instance and exec()uting it yourself when unpickling by adding a __reduce__() method that passes the class definition to a callable. Here's a trivial example illustrating what I mean:
from textwrap import dedent
# Scaffolding
definition = dedent('''
class MyClass(object):
def __init__(self, attribute):
self.attribute = attribute
def __repr__(self):
return '{}({!r})'.format(self.__class__.__name__, self.attribute)
def __reduce__(self):
return instantiator, (definition, self.attribute)
''')
def instantiator(class_def, init_arg):
""" Create class and return an instance of it. """
exec(class_def)
TheClass = locals()['MyClass']
return TheClass(init_arg)
# Sample usage
import pickle
from io import BytesIO
stream = BytesIO() # use a memory-backed file for testing
obj = instantiator(definition, 'Foo') # create instance of class from definition
print('obj: {}'.format(obj))
pickle.dump(obj, stream)
stream.seek(0) # rewind
obj2 = pickle.load(stream)
print('obj2: {}'.format(obj2))
Output:
obj: MyClass('Foo')
obj2: MyClass('Foo')
Obviously it's inefficient to include the class definition string with every class instance pickled, so that redundancy may make it impractical, depending on the the number of class instances involved.

Categories