Python: How to get attribute of attribute of an object with getattr?
Question:
How do I evaluate
a = myobject.id.number
and return None if it myobject is None
with built-in getattr
? Maybe getattr(myobject, "id.number", None)
?
Answers:
A slightly over generic solution keeping in view all members:
if myobject and myobject.id and myobject.id.number:
a = myobject.id.number
else:
a = None
getattr(getattr(myobject, "id", None), "number", None)
should work.
Here’s a one-liner
a = myobject is not None and myobject.id.number or None
It doesn’t check whether id is None, but that wasn’t part of the original question.
return myobject.id.number if myobject else None
This should scale well to any depth:
reduce(lambda obj, attr : getattr(obj, attr, None), ("id","num"), myobject)
my favorites are
from functools import reduce
try:
a = reduce(getattr, ("id", "number"), myobject)
except AttributeError:
a = None
or
from operator import attrgetter
try:
a = attrgetter('id.number')(myobject)
except AttributeError:
a = None
I use the following function which does it for any level.
def Resolve(object, attribute:str):
"""
Resolve attribute of an object.
"""
attribute_list = attribute.split(".")
obj = object
try:
for att in attribute_list:
obj = getattr(obj, att)
except AttributeError:
obj = None
return obj
To use it you write:
a = Resolve(myobject, 'id.number')
The code simply splits the string using the the period character and loops through the attributes. If you had another level say `myobject.id.number.another’ you would use:
a = Resolve(myobject, 'id.number.another')
How do I evaluate
a = myobject.id.number
and return None if it myobject is None
with built-in getattr
? Maybe getattr(myobject, "id.number", None)
?
A slightly over generic solution keeping in view all members:
if myobject and myobject.id and myobject.id.number:
a = myobject.id.number
else:
a = None
getattr(getattr(myobject, "id", None), "number", None)
should work.
Here’s a one-liner
a = myobject is not None and myobject.id.number or None
It doesn’t check whether id is None, but that wasn’t part of the original question.
return myobject.id.number if myobject else None
This should scale well to any depth:
reduce(lambda obj, attr : getattr(obj, attr, None), ("id","num"), myobject)
my favorites are
from functools import reduce
try:
a = reduce(getattr, ("id", "number"), myobject)
except AttributeError:
a = None
or
from operator import attrgetter
try:
a = attrgetter('id.number')(myobject)
except AttributeError:
a = None
I use the following function which does it for any level.
def Resolve(object, attribute:str):
"""
Resolve attribute of an object.
"""
attribute_list = attribute.split(".")
obj = object
try:
for att in attribute_list:
obj = getattr(obj, att)
except AttributeError:
obj = None
return obj
To use it you write:
a = Resolve(myobject, 'id.number')
The code simply splits the string using the the period character and loops through the attributes. If you had another level say `myobject.id.number.another’ you would use:
a = Resolve(myobject, 'id.number.another')