0

I have a list of object attributes that I wish to re-assign. Some of the attributes are within nested objects. Is there a simple way to assign all of these attributes using a single loop or otherwise.

Here is my example code:

from datetime import datetime
import time

class Foo:
  pass

class Bar:
  pass

now = time.time()

foo = Foo()
foo.time1 = now
foo.time2 = now + 1000
foo.other = 'not just times'

foo.bar = Bar()
foo.bar.btime1 = now - 1000
foo.bar.btime2 = now - 2000
foo.bar.bother = 'other stuff'

## seemingly easy way
# just sets time to reference the result, doesn't alter foo
for time in foo.time1, foo.time2, foo.bar.btime1, foo.bar.btime2:
  time = datetime.fromtimestamp( time ).strftime('%c')

## 'dirty' way
for time in 'time1', 'time2':
  val = getattr(foo, time)
  val = datetime.fromtimestamp( val ).strftime('%c')
  setattr( foo, time, val )

# have to do another loop for each nested object
for time in 'btime1', 'btime2':
  val = getattr(foo.bar, time)
  val = datetime.fromtimestamp( val ).strftime('%c')
  setattr( foo.bar, time, val )

# goal is to format everything nicely...
print (
    'Time1:  {0.time1}\n'
    'Time2:  {0.time2}\n'
    'Other:  {0.other}\n'
    'BTime1: {0.bar.btime1}\n'
    'BTime1: {0.bar.btime2}\n'
    'BOther: {0.bar.bother}'
    ).format(foo)

Being the python noob that I am, I tried looping through the attributes first and obviously that didn't work for well documented reasons. The only alternative I can see is using setattr, however this doesn't work well with the nested objects as shown. Although it 'feels like' there should be an easier way to do the assignments since this is a simple thing to achieve with pointers in other languages.

To be clear this question is about the nested object assignments. But since I am obviously attempting to convert an object containing timestamps to a one containing formatted date/time strings and print it, any other suggestions on how to get to the formatted output would be helpful :)

1 Answer 1

2

In general, this sort of thing is really a design problem that is only pretending to be an implementation problem. To solve it, reorganize so that you do the work up front. Of course, presumably the reason you didn't do this the first time around was in order to avoid duplication of the time formatting code. But simply by saying that, the solution becomes obvious: wrap it in a function.

def formatted_time(timestamp):
    return datetime.fromtimestamp(timestamp).strftime('%c')

foo = Foo()
foo.time1 = formatted_time(now)
foo.time2 = formatted_time(now + 1000)
foo.other = 'not just times'

foo.bar = Bar()
foo.bar.btime1 = formatted_time(now - 1000)
foo.bar.btime2 = formatted_time(now - 2000)
foo.bar.bother = 'other stuff'
Sign up to request clarification or add additional context in comments.

2 Comments

Yeah, this is probably the correct way to be doing it. Looping seemed like a good way to avoid a long list of assignments (in my full code the objects come from a library). I was more curious to see if there was a simple way for that kind of approach to work. Thank you for the problem solving approach though.
I assumed you had the assignments already, based on the example code. A better-tailored solution requires a more accurate description of the problem.

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.