Reputation: 65
This has been taxing me for some time, so it's possible what I am trying to do is not a good thing, so I need either the solution to my problem or a recommendation of how to do it right.
I have a spreadsheet full of data which I need to transform. The spreadsheet can have 140 or more columns, and I want to make this dynamic, so if someone changes the columns in the spreadsheet it still works. So my spreadsheet might look like this:
THISFIELDTHATFIELDTHIRDFIELD
ABCD 123 Text
EFGH 456 Other text
etc (man, making a table here is HARD!)
This works fine, and I am guessing you know there is a but coming:
class MyThing:
pass
def __init__(self, **kwargs):
for attribute, value in kwargs.iteritems():
setattr(self, attribute, value)
def validate_my_thing(self):
self.ATTRIBUTE = whatever I want to do with that attribute
If I instantiate MyThing like this:
new_thing = MyThing(THISFIELD="ABCD", THATFIELD=123, THIRDFIELD="Text")
It works perfectly. So the problem is I want to take the attribute names from the spreadsheet (which I can do, I don't need to know how to read a spreadsheet), and populate the attribute values from the columns in the spreadsheet. If I could instantiate the class like this:
new_thing = Mything({"THISFIELD": "ABCD", "THATFIELD": 123, THIRDFIELD: "TEXT"})
then my life would be easy.
Just to re-iterate, instantiating the class like:
new_thing = MyThing(THISFIELD = worksheet_cell(1,2))
won't work, like I said there might be 140 attributes, and I don't want the instantiation to be static, it has to be dynamic.
Upvotes: 1
Views: 113
Reputation: 37606
Either change your constructor to:
def __init__ (self, fields):
for attribute, value in fields.items():
setattr(self, attribute, value)
Or call it with **
:
new_thing = Mything(**{"THISFIELD": "ABCD", "THATFIELD": 123, THIRDFIELD: "TEXT"})
Note: If one of the keys is not a valid attribute name (e.g. 1
), the first method will fail in setattr
while the second will fail before calling the constructor.
Upvotes: 1
Reputation: 59273
Something like this should work:
def __init__(self, fields):
for attribute, value in fields.iteritems():
setattr(self, attribute, value)
All I've done is changed **kwargs
to fields
in the argument list (because you're passing in an actual dict
).
Upvotes: 2