python - getattr and setattr on nested objects? -


this simple problem hopefuly easy point out mistake or if possible.

i have object has multiple objects properties. want able dynamically set properties of these objects so:

class person(object):     def __init__(self):         self.pet = pet()         self.residence = residence()  class pet(object):     def __init__(self,name='fido',species='dog'):         self.name = name         self.species = species  class residence(object):     def __init__(self,type='house',sqft=none):         self.type = type         self.sqft=sqft   if __name__=='__main__':     p=person()     setattr(p,'pet.name','sparky')     setattr(p,'residence.type','apartment')     print p.__dict__ 

the output is:

{'pet': <main.pet object @ 0x10c5ec050>, 'residence': <main.residence object @ 0x10c5ec0d0>, 'pet.name': 'sparky', 'residence.type': 'apartment'}

as can see, rather having name attribute set on pet object of person, new attribute "pet.name" created.

i cannot specify person.pet setattr because different child-objects set same method, parsing text , filling in object attributes if/when relevant key found.

is there easy/built in way accomplish this?

or perhaps need write recursive function parse string , call getattr multiple times until necessary child-object found , call setattr on found object?

thank you!

you use functools.reduce:

import functools  def rsetattr(obj, attr, val):     pre, _, post = attr.rpartition('.')     return setattr(rgetattr(obj, pre) if pre else obj, post, val)  sentinel = object() def rgetattr(obj, attr, default=sentinel):     if default sentinel:         _getattr = getattr     else:         def _getattr(obj, name):             return getattr(obj, name, default)     return functools.reduce(_getattr, [obj]+attr.split('.')) 

rgetattr , rsetattr drop-in replacements getattr , setattr, can handle dotted attr strings.


import functools  class person(object):     def __init__(self):         self.pet = pet()         self.residence = residence()  class pet(object):     def __init__(self,name='fido',species='dog'):         self.name = name         self.species = species  class residence(object):     def __init__(self,type='house',sqft=none):         self.type = type         self.sqft=sqft  def rsetattr(obj, attr, val):     pre, _, post = attr.rpartition('.')     return setattr(rgetattr(obj, pre) if pre else obj, post, val)  sentinel = object() def rgetattr(obj, attr, default=sentinel):     if default sentinel:         _getattr = getattr     else:         def _getattr(obj, name):             return getattr(obj, name, default)     return functools.reduce(_getattr, [obj]+attr.split('.')) 

if __name__=='__main__':     p = person()     print(rgetattr(p, 'pet.favorite.color', 'calico'))     # 'calico'      try:         # without default argument, `rgetattr`, `getattr`, raises         # attributeerror when dotted attribute missing         print(rgetattr(p, 'pet.favorite.color'))     except attributeerror err:         print(err)         # 'pet' object has no attribute 'favorite'      rsetattr(p, 'pet.name', 'sparky')     rsetattr(p, 'residence.type', 'apartment')     print(p.__dict__)     print(p.pet.name)     # sparky     print(p.residence.type)     # apartment 

Comments

Popular posts from this blog

OpenCV OpenCL: Convert Mat to Bitmap in JNI Layer for Android -

android - org.xmlpull.v1.XmlPullParserException: expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope -

python - How to remove the Xframe Options header in django? -