How to instantiate a class given its name as a string? [duplicate] - python

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 8 years ago.
Give some class definitiona in python, e.g.
class A(object):
def __init__(self):
self.x = 5
class B(object):
def __init(self):
self.x = 42
I want to instantiate one of these classes given its name as string. So for example, if classname is A, then I want to do something like
myinstance = SOMETHING(classname)
which should correspond to
myinstance = A()
Is there a way to do this without the use of eval eval or maps? If not, I would do the following:
map = {'A': A, 'B': B}
myinstance = map[classname]()

Considering that the Python naming scheme is based on maps, you will be using maps of one sort or another even if you use eval.
Building your own map is the most appropriate, but you can also use globals() or retrieve it from a module if your classes are stored somewhere else:
import util_module
getattr(util_module, 'A') ()

Related

How can I create classes with different class attributes within a function? [duplicate]

This question already has answers here:
Creating a class within a function and access a function defined in the containing function's scope [duplicate]
(2 answers)
Closed 2 years ago.
I would like to have a function that allows generating classes with custom class attributes. Like so:
def test_factory(a):
class Test:
a = a
return Test
However, when I try to call test_factory, I get an error:
test_factory(1)
> NameError: name 'a' is not defined
The expected behaviour would be:
t1 = test_factory(1)
t2 = test_factory(2)
print(t1.a, t2.a)
> 1, 2
How can I create classes that differ in their class attributes by calling a function?
You have to rename the function argument to not collide with the name of the class attribute:
def test_factory(b):
class Test:
a = b
return Test
>>> t1 = test_factory(1)
>>> t2 = test_factory(2)
>>> print(t1.a, t2.a)
1 2
When parsing the class statement, the assignment to a defines it as part of the temporary class namespace, similar to an assignment to a local variable in a function definition. As such, the name a then shadows the name of the parameter in the enclosing function scope.
You can either change the parameter name (as shown by schwobaseggl)
def test_factory(a_value):
class Test:
a = a_value
return Test
or set the attribute after the definition:
def test_factory(a):
class Test:
pass
Test.a = a
return Test
or call type directly:
def test_factory(a):
return type('Test', (), {'a': a})

How to create an instance of a class from a string name of the instance? [duplicate]

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 2 years ago.
I would like to create several instances of a Class, I tried to make a for loop to name them differently.
Something like this, which doesn't work because the instance name is not supposed to be a string:
class A:
pass
for i in range(10):
"a"+str(i) = A()
Here the result I expect is 10 instances of the class A named: a0, a1, ... , a9.
How should I do?
You can use dictionaries,
classes = {}
for i in range(10):
classes[f"a{i}"] = A()
Then you can access the class instance like this classes["a7"].
i can think in two ways.
The trash way and a good way
Thrash:
class A:
pass
for i in range(10):
eval("a"+str(i)) = A()
Good:
class A:
pass
a= []
for i in range(10):
a[i] = A()

call method without parenthesis in python [duplicate]

This question already has answers here:
What's the pythonic way to use getters and setters?
(8 answers)
Closed last month.
what modification i would need to do in the below function computeDifference to get result printed in the console, instead of object message.
i know i need to add parenthesis () to call function to get the result printed in the console, but is there any other way to print the result?
class Difference1:
def __init__(self, a):
self.__elements = a
def computeDifference(self):
self.difference = max(self.__elements)- min(self.__elements)
return self.difference
a = [5,8,9,22,2]
c = Difference1(a)
print(c.computeDifference)
Make it a property
class Difference1:
#property
def computeDifference(self):
...
print(c.computeDifference)
However, I would change the name to difference. The idea of a property is that you shouldn't know or care whether the value is computed at that time or is stored as an attribute of the object. See uniform access principle.
You could add a magic function:
class Difference1:
...
def __str__(self):
return str(self.computeDifference())
...
>>> a = [5,8,9,22,2]
>>> c = Difference1(a)
>>> print(c)
20

Instance from another instance in Python [duplicate]

This question already has answers here:
Copy constructor in python?
(8 answers)
Closed 6 years ago.
In C++, the constructor of a class allows an instance to be constructed from another instance. e.g.
C::C(const C & c) {
bala...;
cc = c.cc;
}
In Python, what is the similar way of doing this? How may I use
c1 = C()
c2 = C(c1)
?
We don't mention the type while defining a variable in python. For example: if x=4, you can always set x to something else, x="shasha". No problem at all.
Note we can not overload a method in python.
Coming back to your question:
Assuming that you understand the python memory management and the difference between a reference and an actual value, You may use deepcopy feature in python:
import copy
class A(object):
def __init__(self):
self.a=10
x = A()
y= copy.deepcopy(x)
x.a=15
print(y.a) # prints 10.
Note that you can always copy one object into another using = operator like y = x but it wont actually copy anything. Now both the references y and x will actually be pointing to the same instance. i.e. if you change anything using one, it will automatically be reflected into the other one:
class A(object):
def __init__(self):
self.a=10
x = A()
y = x
x.a=15
print(y.a) # prints 15.
You can also create a dummy constructor as mentioned in following example:
class A:
def __init__(self):
self.a=10
def dummy_constructor(self):
temp = A()
temp.a = (self.a + 20 - 5 )*100/10
return temp
x=A()
y=x.dummy_constructor()
print(y.a) #250
print(x.a) #10

How to dynamically compose and access class attributes in Python? [duplicate]

This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 3 years ago.
I have a Python class that have attributes named: date1, date2, date3, etc.
During runtime, I have a variable i, which is an integer.
What I want to do is to access the appropriate date attribute in run time based on the value of i.
For example,
if i == 1, I want to access myobject.date1
if i == 2, I want to access myobject.date2
And I want to do something similar for class instead of attribute.
For example, I have a bunch of classes: MyClass1, MyClass2, MyClass3, etc. And I have a variable k.
if k == 1, I want to instantiate a new instance of MyClass1
if k == 2, I want to instantiate a new instance of MyClass2
How can i do that?
EDIT
I'm hoping to avoid using a giant if-then-else statement to select the appropriate attribute/class.
Is there a way in Python to compose the class name on the fly using the value of a variable?
You can use getattr() to access a property when you don't know its name until runtime:
obj = myobject()
i = 7
date7 = getattr(obj, 'date%d' % i) # same as obj.date7
If you keep your numbered classes in a module called foo, you can use getattr() again to access them by number.
foo.py:
class Class1: pass
class Class2: pass
[ etc ]
bar.py:
import foo
i = 3
someClass = getattr(foo, "Class%d" % i) # Same as someClass = foo.Class3
obj = someClass() # someClass is a pointer to foo.Class3
# short version:
obj = getattr(foo, "Class%d" % i)()
Having said all that, you really should avoid this sort of thing because you will never be able to find out where these numbered properties and classes are being used except by reading through your entire codebase. You are better off putting everything in a dictionary.
For the first case, you should be able to do:
getattr(myobject, 'date%s' % i)
For the second case, you can do:
myobject = locals()['MyClass%s' % k]()
However, the fact that you need to do this in the first place can be a sign that you're approaching the problem in a very non-Pythonic way.
OK, well... It seems like this needs a bit of work. Firstly, for your date* things, they should be perhaps stored as a dict of attributes. eg, myobj.dates[1], so on.
For the classes, it sounds like you want polymorphism. All of your MyClass* classes should have a common ancestor. The ancestor's __new__ method should figure out which of its children to instantiate.
One way for the parent to know what to make is to keep a dict of the children. There are ways that the parent class doesn't need to enumerate its children by searching for all of its subclasses but it's a bit more complex to implement. See here for more info on how you might take that approach. Read the comments especially, they expand on it.
class Parent(object):
_children = {
1: MyClass1,
2: MyClass2,
}
def __new__(k):
return object.__new__(Parent._children[k])
class MyClass1(Parent):
def __init__(self):
self.foo = 1
class MyClass2(Parent):
def __init__(self):
self.foo = 2
bar = Parent(1)
print bar.foo # 1
baz = Parent(2)
print bar.foo # 2
Thirdly, you really should rethink your variable naming. Don't use numbers to enumerate your variables, instead give them meaningful names. i and k are bad to use as they are by convention reserved for loop indexes.
A sample of your existing code would be very helpful in improving it.
to get a list of all the attributes, try:
dir(<class instance>)
I agree with Daenyth, but if you're feeling sassy you can use the dict method that comes with all classes:
>>> class nullclass(object):
def nullmethod():
pass
>>> nullclass.__dict__.keys()
['__dict__', '__module__', '__weakref__', 'nullmethod', '__doc__']
>>> nullclass.__dict__["nullmethod"]
<function nullmethod at 0x013366A8>

Categories