How can I generate class instances dynamically? Specifically, what I'm looking to do:
I'm pulling in data from a spreadsheet, which gets converted to CSV. The row is the header. After the header row, each row represents data about a particular order (col1 is the order ID, col2 is the customer name, col 3 is the date, col 4 is the quantity, etc.). Right now, I'm importing the CSV to a list of dictionaries. So each item in the list stores a dictionary that pulls the key from the header row. So, I could lookup the quantity of order #5 by:
orderDict[5]['quantity']
I'm very new to object-oriented programming... but would like to make each of these orders an instance of the Order class. So, I'd like to create a class called "Order" then have it pull the properties from the header row of the CSV. So, something like (inputList is the list that was pulled in from the CSV file):
class Order(object):
"""Defines an individual order"""
def __init__(self, inputList):
for z in range(len(inputList[0]))
self.inputList[0][z] = None
I'd then like to have some code that goes through the data imported from the CSV and creates an instance for each row.
for a in range(len(inputList))
if a != 0:
orderName = 'order%d' % (a)
orderName = Order() #I know this won't work... but not sure how I variably name this
for b in range(len(inputList[a]))
orderName.b = inputList[a][b]
The result would be an instance called order1, order2, order3, order4, etc. The number of instances created would be dependent on the number of rows in the original data. Could be 4... could be thousands.
This way, if I want to find the quantity of order 5, I can just call for:
order5.quantity
However, so far it appears that I would need to explicitly create each instance manually:
order1 = Order()
order2 = Order()
order3 = Order()
Not very convenient or dynamic when dealing with thousands of orders (and growing). Seems like there should be a way to dynamically generate these instances based on the data being fed into the program.
If you really want the instances to have global variable names (e.g. order1, order2, etc) it is possible (but very ugly) using e.g. globals()['order' + num] = Order(...). The far cleaner and safer way would be to store the instances in a single dict. Also for the sake of efficiency, you could pop the header to avoid the test for zero from each iteration, could use xrange instead of range to avoid slurping complete sets of data around, could optionally set the attributes in the object's init rather than afterwards (seeing the info is already available...), and could pass only the header and line to each instantiation rather than all the data. By the way there are colons missing from the ends of your for-lines:
class Order(object):
"""Defines an individual order"""
def __init__(self, input_header, input_line):
for z in xrange(len(input_header)):
setattr(self, input_header[z], input_line[z])
orders = {}
input_header = input_list.pop(0)
for a in xrange(len(input_list)):
orders[a] = Order(input_header, input_list[a])
the general solution to this is to use a dictionary mapping strings to classes
classes = {"order":Order,"something":Something}
keys = ["order","order","something"]
my_instances = [classes[key]() for key in keys]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With