Python: how to automatically create instance object? - python

I want to create instance objects automatically as I explained in the following:
Class MyClass:
def __init__(self,x):
self.x = x
list = ["A","B"]
I want to create the following but automatically, means to loop through the list and create identical object for each element:
A = MyClass(text)
B = MyClass(text)
e.g. like the following which doesn't work:
# this doesn't work but explains more what I need
for i in list:
i = MyClass(text)
Thanks to all of your help!

In general, you can't and shouldn't shove things into your namespace like that. It's better to store those instances in a dict or a list
Class MyClass:
def __init__(self,x):
self.x = x
lst = ["A","B"] # don't use list as an identifier
myclasses = {k: MyClass(text) for k in lst}
Now your instances are
myclasses['A'], myclasses['B'] etc.
If you really want to create a handful of variables in your namespace:
A, B = (MyClass(text) for x in range(2))
note that this means you need to be explicit. You can't get the A,B from a file or user input etc.
Don't be tempted to use exec to pull this off. It's probably the wrong way to go about solving your problem. Tell us why you think you need to do it instead.

Related

Declaring several python classes in a loop?

I have a generic class definition, something like this -
class Foo(object):
property = 1
def __init__(self, ...):
...
I wish to create a large number of classes, each of which has a different value of property, and store these classes in a list. The classes in this list will be subsequently used to create several objects.
What is the best way to do this?
While I doubt that there isn't a better solution to whatever your underlying problem might be, you can create classes dynamically using type:
class Foo(object):
def __init__(self, x):
self.x = x
# class-name---vvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvv--class-attributes
klasses = [type('Foo{}'.format(n), (Foo,), {'property': n}) for n in range(5)]
# parent-classes ^^^^^^
klasses[4]
# <class '__main__.Foo4'>
klasses[4].property
# 4
inst = klasses[4]('bar')
inst.x
# 'bar'
c = []
for i in range(5):
class X(object):
property = i
def __init__(self):
print(self.property)
c.append(X)
c[0]() # will print 0
c[4]() # will print 4
But this has a bunch of drawbacks. I also think that the comment given below the question is remarkable. Very likely you strive for a solution which is not the best for your original problem.
If you really want to do it, then sure you can create classes dynamically using type
class BaseClass(object):
# the code that needs to be common among all classes
properties = [1, 2, 3]
classes = [type("class_{0}".format(i), (BaseClass,), {'property': property}) for i, property in enumerate(properties)]
However, you probably need to think about your design. I don't know about the problem you want to solve, but perhaps keeping the property variable as instance one would make more sense.
I think the best way would just be to iterate i=0 to n-1, appending a new object to the end of the list. You can then use i to index into the list and change the value of property that way.

Creating a variable number of class instances

My Class:
class myClass:
pass
I am looking to recreate this effect:
x = myClass()
y = myClass()
z = myClass()
within a for loop because the number of times I need to loop will be varied each time.
Trying this:
x = 3
for i in range(x):
cls = myClass()
doesn't work because on each iteration I recreate the class instance.
My thinking is that on each loop I need to create a copy of the class and store that in a dict for referencing. So my questions are:
Is this the right approach?
How do I create a copy of a class?
My attempts to create a class so far have been unsuccessful as the class isn't totally individual.
x = deepcopy(cls)
CopyOfCls = type('CopyOfCls', cls.__bases__, dict(cls.__dict__))
EDIT: Answerers revealed that I was actually looking at creating multiple class instances.
You don't need to copy a class to make multiple instances of that class.
items = []
for i in range(10):
items.append(myClass())
items now contains ten separate myClass instances. You can access them individually with indexing, ex. items[3].

Python - Proper way of serially reassign/update class members

I have a class whose members are lists of numbers built by accumulating values from experimental data, like
class MyClass:
def __init__(self):
container1 = []
container2 = []
...
def accumulate_from_dataset(self,dataset):
for entry in dataset:
container1.append( foo (entry) )
container2.append( bar (entry) )
...
def process_accumulated_data(self):
'''called when all the data is gathered
'''
process1(container1)
process2(container2)
...
Issue: it would be beneficial if I could convert all the lists into numpy arrays.
what I tried: the simple conversion
self.container1 = np.array(self.container1)
works. Although, if I would like to consider "more fields in one shot", like
lists_to_convert = [self.container1, self.container2, ...]
def converter(lists_to_convert):
for list in lists_to_convert:
list = np.array(list)
there is not any effective change since the references to the class members are passed by value.
I am thus wondering if there is a smart approach/workaround to handle the whole conversion process.
Any help appreciated
From The Pragmatic Programmer:
Ask yourself: "Does it have to be done this way? Does it have to be done at all?
Maybe you should rethink your data structure? Maybe some dictionary or a simple list of lists would be easier to handle?
Note that in the example presented, container1 and container2 are just transformations on the initial dataset. It looks like a good place for list comprehension:
foo_data = [foo(d) for d in dataset]
# or even
foo_data = map(foo, dataset)
# or generator version
foo_data_iter = (foo(d) for d in dataset)
If you really want to operate on the instance variables as in the example, have a look at getattr and hasattr built-in functions
There isn't an easy way to do this because as you say python passes "by-reference-by-value"
You could add a to_numpy method in your class:
class MyClass:
def __init__(self):
container1 = []
container2 = []
...
def to_numpy(self,container):
list = self.__getattr__(container)
self.__setattr__(container,np.array(list))
...
And then do something like:
object = MyClass()
lists_to_convert = ["container1", "container2" ...]
def converter(lists_to_convert):
for list in lists_to_convert:
object.to_numpy(list)
But it's not very pretty and this sort of code would normally make me take a step back and think about my design.

Simple OOP: Python, saving object names via __init__ v2

OK, I asked a similar question before but was too confusing because of my lack of correct terminology. This is my second bite at the apple.
I want to create an object whose __init__ will save the name assigned to the object in a list.
kinda like this:
class Object():
def __init__(self, something):
self.something = something
(now how do I save the xxx, xx, and x names I create below?)
xxx = Object(something)
xx = Object(something)
x = Object(something)
I want a global total_objects (or whatever) that contains [xxx, xx, x]
Sorry for the crummy formatting. I hope my question is still clear.
such as:
total_objects = [xxx, xx, x]
Also, please let me know if my approach is sloppy and there's a better way, but I don't want to have to save the 'x' names in the code itself. Such as total_objects.append(xxx) total_objects.append(xx) etc. I want it to be automatic.
You can't do exactly this in Python, because there's nothing requiring an object to be assigned to a specific name, so the initializer doesn't get passed such info.
For instance, the following lines are all valid Python:
x = Object()
y = x
Object()
[Object() for i in xrange(5)]
x = [Object() for i in xrange(5)]
If you want to keep track of the instances of the object, you can do that, but that's separate from the names that reference those instances:
class Object(object):
my_instances = []
def __init__(self):
my_instances.append(self)
Then Object.my_instances would contain a list of the instances:
[<__main__.Object instance at 0x012BA760>, ...]
However this may not be what you want.
lis = []
class Object():
def __init__(self, var):
self.something = var
lis.append(self) #here self is the reference to the instance being created and you can save it in a list to access it later
xxx = Object('123')
xx = Object('12')
x = Object('1')
for x in lis:
print(x.something)
output:
123
12
1

Generate Class Instance In Python

I have been having trouble getting python to generate a (non-predetermined) number of class instances. Basically have classes be able to reproduce themselves.
class foo:
def __init__(self, name):
self.name = name
while True:
newinstance(foo) #what would the code be for this?
#or maybe
foo.newinstance #just something that could update itself
Basically generate a new instance any number of times. Thanks ahead of time.
This will do what you're asking for, but you'll want to hold onto the values somehow:
while True:
foo(some_name)
This will loop forever, so a more realistic option might be:
names = ["Ned", "Felix", "Guy"]
fooses = [foo(name) for name in names]
Use a list comprehension:
instances_of_foo = [foo("bar") for i in range(number_of_instances)]
Also, if you would like to pass different arguments to each instance, you can create of list of args instead of using range().
list_of_args = [args_for_instance_one, args_for_instance_two,...]
instances_of_foo = [foo(arg) for arg in list_of_args]

Categories

Resources