Whether code should fail or just return some default value is a matter of opinion or style. Where ES6 defaults to undefined
, other languages might pick something like null
- in Python you might expect None
.
However, multiple choices are available, and for some types, a value of 0
might make sense and None
could cause havoc, so Python chooses to cause your code to fail when it accesses non-existent attributes.
There's a few ways to deal with it gracefully though.
try .. except
:
try:
x = theObject.nestedObjectOne.NestedObjectTwo.NestedObjectThree
except AttributeError:
x = None # or whatever value makes the most sense
Without exceptions:
x = getattr(
getattr(
getattr(
theObject, 'nestedObjectOne', None
),
'nestedObjectTwo', None
),
'nestedObjectThree', None
)
(obviously, you can write it on a single line if you don't mind the lack of readability)
Or you could modify the class so that it deals with the case of a non-existent attribute gracefully itself, which can make sense in specific case without being "unpythonic".
For example:
class MyClass:
has_this = 42
def __getattr__(self, item):
if item in self.__dict__:
return self.__dict__[item]
else:
return None
x = MyClass()
print(x.has_this)
print(x.does_not_have_this)
Note that this is a somewhat simplistic and incomplete way to implement this, it's here to show the direction you could be looking in. Of course, you can have MyClass
inherit from any other class, to add the behaviour to an existing class.