[Tutor] Creating class instances through iteration

Steven D'Aprano steve at pearwood.info
Fri Apr 16 08:30:26 CEST 2010


On Fri, 16 Apr 2010 12:03:52 pm Tim Goddard wrote:

> For example each row would look like [name, value1, value2, value3],
> I planned on passing the three values as a tuple
>
> The code would simply be:
>
> for row in csvimport:
>     tuple = (row[1],row[2],row[3])
>     instancename = Classname(tuple)
>
> How could I create different instances inside an iteration loop for
> each row ? 

Let me see if I have it right... you want a CSV file that looks 
something like this:

a,1,2,3
b,2,4,8
c,3,6,9


and you want to end up with:

a = Classname((1,2,4))
b = Classname((2,4,8))
c = Classname((3,6,9))


Correct?

That's the wrong question. It's easy to create new names, using eval 
(but beware of the security risks!). But the question you should be 
asking is, what on earth do I do with them once I've created them?

Later in your code, suppose you want to do something like this:

print c.some_method()


(say). But how do you know that c will exist? Maybe the CSV file doesn't 
have rows named a,b,c, but instead has x,y,z. Or a,b,d,e, or even 
fred,wilma,betty,barney. Since you don't know what the name of the 
variable will be, you can't refer to it in code. You then have to jump 
through all sorts of flaming hoops by writing code like this:

# Untested
list_of_names = []
for row in csvimport:
    list_of_names.append(row[0])
    tuple = (row[1],row[2],row[3])
    # WARNING -- the next line is DANGEROUS and has a HUGE security
    # hole which could cause data loss. Only use it on data you 
    # trust with your life.
    eval('%s = Classname(t)' % row[0], globals(), {'t': tuple})
# more code goes here
# ...
# much later
if 'c' in list_of_names:
    print c.some_method()
else:
    # Oh I don't know, just pick some random variable and hope it
    # is the right one...
    eval('print %s.some_method()' % list_of_names[0])


Whew! Ugly, insecure, slow, dangerous code.

Is there an alternative? Of course -- dictionaries.


objects = {}
for row in csvimport:
    tuple = (row[1],row[2],row[3])
    objects[row[0]) = Classname(tuple)
# more code goes here
# ...
# much later
try:
    print objects['c'].some_method()
except KeyError:
    # No name 'c' exists...
    ...


But more likely, you don't need to operate on a single object c, you 
need to operate on all of them. So what is the purpose of the names? 
Just drop the names, and work on a collection of objects:

objects = []
for row in csvimport:
    tuple = (row[0],row[1],row[2])
    objects.append(Classname(tuple))
# more code goes here
# ...
# much later
for obj in objects:
    print obj.some_method()


Hope this helps,




-- 
Steven D'Aprano


More information about the Tutor mailing list