简体   繁体   中英

Python: easy way to loop through and assign nested object attributes?

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

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'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM