Creating alot of class instances?

K

kk

Hi

I am new to Python classes and trying to figure out this particular
issue here. I will need to create instances of a class. But at the
moment I do not know how many instances I will end up having, in every
case it might be different. Most of the documents I read makes this
simpl class-student analogy to explain python classes which is fine.
But in those examples the number and the names of the instances were
known and limited.

I will be querying some data and create class instances based on the
data I gather. But the problem as I mentioned is that I do not know
the names and the number of the end class instances. They will be
based on the content of the data. So how can I create class instances
within a loop and when the loop is done how can I figure out the list
of instances via class membership? I can track the names by
introducing another list but I want to understand the class side of
things.

The solution might be dead simple but I just cannot figure out at the
moment.

For example this is what I need in the simplest form

class myclass():
def __init__(self,name):
self.name=name

for count,data in enumerate(some list):
instance_count=myclass()
instance_count.name=data

print instances


thanks
 
A

Andre Engels

I am new to Python classes and trying to figure out this particular
issue here. I will need to create instances of a class. But at the
moment I do not know how many instances I will end up having, in every
case it might be different. Most of the documents I read makes this
simpl class-student analogy to explain python classes which is fine.
But in those examples the number and the names of the instances were
known and limited

That's no problem. The only limit to the number of instances of a
class you can create is your memory - and not even that if you don't
need to 'keep' the instances.
I will be querying some data and create class instances based on the
data I gather. But the problem as I mentioned is that I do not know
the names and the number of the end class instances. They will be
based on the content of the data. So how can I create class instances
within a loop and when the loop is done how can I figure out the list
of instances via class membership? I can track the names by
introducing another list but I want to understand the class side of
things.

The solution might be dead simple but I just cannot figure out at the
moment.

For example this is what I need in the simplest form

class myclass():
def __init__(self,name):
self.name=name

for count,data in enumerate(some list):
instance_count=myclass()
instance_count.name=data

print instances

Okay, to solve your problem, we add a list containing all the instances:

class myclass():
def __init__(self,name):
self.name=name

instances = []

for count,data in enumerate(some list):
instance_count=myclass()
instance_count.name=data
instances.append(instance_count)

print instances

=============================================

However, that won't work because myclass has an __init__ with 2
attributes, so you will have to call it using an attribute:

class myclass():
def __init__(self,name):
self.name=name

instances = []

for count,data in enumerate(some list):
instance_count=myclass(data)
instances.append(instance_count)

print instances

=============================================

This works, but it can be done better:

First we notice that count is not used at all, so why create it?


class myclass():
def __init__(self,name):
self.name=name

instances = []

for data in some list:
instance_count=myclass(data)
instances.append(instance_count)

print instances

=============================================

Then, the variable instance_count is created once, then used in the
next line. We can do that at once:


class myclass():
def __init__(self,name):
self.name=name

instances = []

for data in some list:
instances.append(myclass(data))

print instances

====================

Finally, "print instances" does not give very nice looking
information, so I would change this to:

class myclass():
def __init__(self,name):
self.name=name

instances = []

for data in some list:
instances.append(myclass(data))

print (instance.name for instance in instances)
 
T

Tim Chase

The solution might be dead simple but I just cannot figure out at the
moment.

For example this is what I need in the simplest form

class myclass():
def __init__(self,name):
self.name=name

for count,data in enumerate(some list):
instance_count=myclass()
instance_count.name=data

print instances

Sounds like a use for a list:

instances = []
for count, data in enumerate(some_list):
# 1) camel-case is preferred for classnames
# 2) since your __init__() expects the name
# pass it in, instead of setting it later
instance = MyClass(data)
instances.append(instance)

This can be written in a slightly more condensed-yet-readable
list-comprehension form as:

instances = [MyClass(data) for data in some_list]

You then have a list/array of instances you can print:

print instances

or pick off certain items from it:

print instances[42]

-tkc
 
K

kk

Hi

Thank you soo much for speedy and in detailed help. Your replies
really cleared out most of the cloud for me. I have one last issue to
resolve which is something I did not articulate properly, I realize
now. The last issue is actually automatically naming the instances.
The reason I was using the "instance_count" is for enumerating the
actual name of an instance.

For example lets say I have

class MyMaterials:

and my instances might need to look like

material_01
material_02
or
light_01
light_02
or
Mesh_01
Mesh_02 etc

I will need to get the base names from the "some list" and create the
names accordingly from the list array.

Basically I also need to generate the instance names based on the some
list. For example some_list[2] might denote a name for the instance.

I will study the sampled codes in depth now. Maybe you have answered
the naming issue as well, if so please frgove the noise.

thanks
 
R

Rickard Lindberg

Thank you soo much for speedy and in detailed help. Your replies
really cleared out most of the cloud for me. I have one last issue to
resolve which is something I did not articulate properly, I realize
now. The last issue is actually automatically naming the instances.
The reason I was using the "instance_count" is for enumerating the
actual name of an instance.

For example lets say I have

class MyMaterials:

and my instances might need to look like

material_01
material_02
or
light_01
light_02
or
Mesh_01
Mesh_02 etc

If you do not know how many instances you are going to create from the
beginning, there is no way for you to know which of the instances you mentioned
above will get created. So having names for all of the instances will not help
you since you will never know what names are "safe" to use.

On the other hand, if you have all instances in a list, you can refer to them
by index and you know exactly how many of them you have.

If you would like to get instances by some name you gave to them, maybe
something like this will work:

def get_instance(name):
for instance in instance_list:
if instance.name == name:
return instance
return None

Note that this might very well return None if no instance with that particular
name was found.
 
T

Tim Chase

For example lets say I have
If you do not know how many instances you are going to create from the
beginning, there is no way for you to know which of the instances you mentioned
above will get created. So having names for all of the instances will not help
you since you will never know what names are "safe" to use.

On the other hand, if you have all instances in a list, you can refer to them
by index and you know exactly how many of them you have.

If you would like to get instances by some name you gave to them, maybe
something like this will work:

def get_instance(name):
for instance in instance_list:
if instance.name == name:
return instance
return None

Another option might be to use a counter in the class that keeps
track of the number of instances:

class MyMaterial:
instances = 0
def __init__(self, name):
self.name = name
self.instance = MyMaterial.instances
MyMaterial.instances += 1
def __str__(self):
return "%s_%02i" % (self.name, self.instance)

m = MyMaterial("Brick")
print m
# "Brick_00"
print repr([MyMaterial("Stone") for _ in range(5)])
# "[Stone_01, Stone_02, Stone_03, Stone_04, Stone_05]"

It's not thread-safe, but it may do the trick.

-tkc
 
K

kk

Hi

Thank you so much for wonderful tips and suggestions.

I also found a solution to dynamic naming of the instances(I think).
It does not sound like a very secure method but since my application
will be just processing data one way I think it might be alright. I
will compare to the list and dictionary methods.

globals()["Some_Instance_Name"]
 
S

Steven D'Aprano

Hi

Thank you so much for wonderful tips and suggestions.

I also found a solution to dynamic naming of the instances(I think). It
does not sound like a very secure method but since my application will
be just processing data one way I think it might be alright. I will
compare to the list and dictionary methods.

globals()["Some_Instance_Name"]


You're fighting the computer instead of working with it. That's the Wrong
Way to solve the problem -- you're doing more work than needed, for
little or no benefit.

My bet is, you have code that looks something like this:


for i in range(N): # N comes from somewhere else
# Create a new variable
globals()["Some_Instance_Name%s" % i] = instance()

# Do something with the variables
for i in range(N):
# Look up the variable
x = globals()["Some_Instance_Name%s" % i]
process(x)


Am I close?

That's the Wrong Way to do it -- you're using a screwdriver to hammer a
nail. The right way to work with an unknown number of data elements is to
put them in a list, and process each element in the list, not to try
giving them all unique names. The only reason for using named variables
is so you can use the name in source code:

my_value = Some_Instance87 + Some_Instance126

But you can't do that, because you don't know how many instances there
are, you don't know whether to write Some_Instance87 or Some_Instance125
or Some_Instance19.


So instead, do something like this:


instances = []
for i in range(N):
# Create a new instance and store it for later
instances.append( instance() )

# Later on:
for x in instances():
process(x)
 
K

kk

Steven,

Before your post I was contemplating about the merits of using the
globals(). After reading your post I am totally convinced that your
suggestion that was also suggested by previous posters is the way to
go. At first I thought it would be limiting to not to have the
instance names properly setup, but now I understand it better.

thank you all again.
 
S

Steven D'Aprano

Don't knock tool abuse (though I agree with you here). Sometimes tool
abuse can produce good results. For example, using hammers to drive
screws for temporary strong holds led to making better nails.

Historically, nails were invented a long time before screws. Screws as
fasteners weren't invented until the 1400s, nails were used thousands of
years ago.

And hammering screws makes temporary *weak* holds, not strong, because
the screw only touches the sides of the hole lightly. Unless the screw
has been specifically designed to be hammered, hammering screws is pretty
much the definition of incompetence and/or laziness!
 
P

Piet van Oostrum

SD> Historically, nails were invented a long time before screws. Screws as
SD> fasteners weren't invented until the 1400s, nails were used thousands of
SD> years ago.
SD> And hammering screws makes temporary *weak* holds, not strong, because
SD> the screw only touches the sides of the hole lightly. Unless the screw
SD> has been specifically designed to be hammered, hammering screws is pretty
SD> much the definition of incompetence and/or laziness!

In our language (Dutch, i.e. Guido's mother tongue) `American
screwdriver' is an expression meaning `hammer' :=)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top