1

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.

2 Answers 2

2

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).

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, as @Holt's answer, will up-vote as soon as it lets me.
1

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.

1 Comment

Thanks, works a treat, will up-vote as soon as it will let me

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.