Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating Class Instances Dynamically in Python

Tags:

python

csv

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.

like image 256
Justin Reusch Avatar asked Aug 01 '26 11:08

Justin Reusch


2 Answers

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])
like image 153
rowanthorpe Avatar answered Aug 03 '26 02:08

rowanthorpe


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]
like image 33
Joran Beasley Avatar answered Aug 03 '26 00:08

Joran Beasley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!