2

I have a class Test that has attributes Test.att1, Test.att2, ... , Test.att10. I have a method Test.update() that computes ten new values vals = [v1, v2, ... , v10]. I'd like to update Test's attributes in a single for loop.

I envision something like looping through the list mylist = [self.att1, self.att2, ... , self.att10] within the Test class and setting values per vals but this didn't seem to work. What can I do instead / what's the best way to update multiple attributes without using a self.att1, self.att2, self.att3 = v1, v2, v3 structure?

EDIT: I'm specifically asking because I am doing something like:

a1, a2, a3, a4, a5 = self.update()
self.a1 = pd.concat([self.a1, a1]).drop_duplicates().reset_index(drop=True)
self.a2 = pd.concat([self.a2, a2]).drop_duplicates().reset_index(drop=True)
self.a3 = pd.concat([self.a3, a3]).drop_duplicates().reset_index(drop=True)
self.a4 = pd.concat([self.a4, a4]).drop_duplicates().reset_index(drop=True)
self.a5 = pd.concat([self.a5, a5]).drop_duplicates().reset_index(drop=True)

and am currently using One backwards way I ended up doing this was:

def update(self):
    dfs = [self.att1, self.att2, ..., self.att10]
    dfs = [pd.concat([dfs[i], vals[i]]).drop_duplicates().reset_index(drop=True) \
                for i in range(len(dfs))]
    [self.att1, self.att2, ..., self.att10] = dfs

but at seeking a better way

2
  • Why don't you write a method which will take the list and update the attributes? it will be easier for you in that way. Commented Sep 7, 2017 at 4:31
  • They all share a similar structure along the lines of pd.concat([self.att1,df]).drop_duplicates().reset_index(drop=True) so I was wondering how to only write once and avoid writing 10 times... Commented Sep 7, 2017 at 4:34

1 Answer 1

1

You could use setattr in combinatin with hasattr to update and add attributes to the target object.

attrs = [a for a in dir(Test) if a.startswith('attr') and 'no_update' not in a]

### To update existing attrs ###
new_vals = [...]
for a, v in zip(attrs, new_vals):
    if hasattr(Test, a):
        setattr(Test, a, v)

### To add new attrs ###
new_vals = [...]
start = int(attrs[-1][4:]) + 1 # the number the new attrs should start at
new_attrs = ['attr%d' % n for n in range(start, start+len(new_vals))] # if start==4 and len(new_vals)==3: return ['attr5', 'attr6', 'attr7']
for a, v in zip(new_attrs, new_vals):
    setattr(Test, a, v)

These can also be combined to allow updating existing attrs and setting new ones if need be.

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

4 Comments

Thanks! What if I want to append v to attribute a as per my update? Is this still a clean way of doing it?
By that do you mean concatenating the new and old attr value? If so, you can get the attr just like you can set and check if it has it like so: setattr(Test, a, getattr(Test, a) + v)
Basically these attributes are pandas DataFrames, and I want to add new lines to an existing 10 or so DataFrames which I have as attributes of Test, but I also have other attributes att_no_update1, ... att_no_update10 that I don't want to update
@jjjjjj I have no experience with pandas and have no idea what a DataFrame is. Regardless, I think I understand what you want and have updated my answer accordingly

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.