0

I have a wtform which has a list of days and start and end time:

form.mon_start
form.mon_end
form.tues_start
form.tues_end
...

I have to set these often and I would like to loop through a list of days and set them in one loop. Something like:

days = ['mon','tues','weds','thurs','fri','sat','sun']
for day in days:
    form.[day + '_start'] = #some datetime setting
    form.[day + '_end'] = #some datetime setting

Is this possible?

0

3 Answers 3

2

You can use setattr(object, attribute, value):

days = ['mon','tues','weds','thurs','fri','sat','sun']
for day in days:
    setattr(form, day + '_start', start_value)
    setattr(form, day + '_end', end_value)

This sets the attribute to value on a given object.

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

4 Comments

This also works for longer variables too? Like setattr(g.currentschool.school_hours,day + '_end',end_value)
Yes, you can use a variable as well to specify the object.
Then does this work? getattr(form,day + '_start').choices. Setting a variable from the dynamic one you got by string.
@Johnston g.currentschool.school_hours is evaluated as ordinary and results in an object (setattr and friends are not special, just ordinary functions). So if you want to set the attribute on the object this evaluates to, then yes that works. Likewise, the getattr call in your second comment just evaluates to an object like every other function call, and if you want to read the choices attribute of the object it results in, then yes that works. These functions aren't magic.
0

You can use setattr(object, name, value).

setattr(form, day+'_start', value)

setattr is a builtin function.

Comments

0

Objects can be thought of as juiced up dictionaries. In fact, they have a dict. So try this:

days = ['mon','tues','weds','thurs','fri','sat','sun']
for day in days:
    form.__dict__[day + '_start'] = #some datetime setting
    form.__dict__[day + '_end'] = #some datetime setting

And you'll get what you want. But its a bit hackish.

The function setattr(, ) does the same thing, its just an explicit (non-hackish) way of doing this, and it should be supported in the future regardless whatever winds up happening to the dict:

days = ['mon','tues','weds','thurs','fri','sat','sun']
for day in days:
    for mark in [('start', gen_start_func), ('end', gen_end_func)]:
        setattr(form, '_'.join([day, mark[0]]), mark[1]())

So in the last version we're using setattr() and we're using an inner loop that operates over a tuple containing (, ). Its a different way of doing things which may or may not be more readable, depending on the problem you're trying to solve and the type of code you are used to reading.

2 Comments

Using getattr / setattr is NOT the same thing as directly accessing the object's __dict__. In the first case you'll trigger the attribute lookup mechanism, which will take proper care of computed attributes, inheritence, dynamic attribute resolution etc. In the second case you totally bypass it, which may yield very unexpected results. Also not all types have a __dict__ (read about slots for more about it).
Indeed, this is true. Perhaps my answer is glossing over too much (whereas usually I cover in too much depth). The story gets much more interesting if the OP is curious. This CafePy article explains a good bit about the inner workings/whys of objects in Python (its an oldie but goodie, still generally applicable to Python3): cafepy.com/article/python_attributes_and_methods/…

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.