I'm trying to construct a list comprehension to create a list of the value of issues.fields.parent.id, or None if there is no parent. Is there a simple way of getting attribute2 of attribute1, and returning a default if attribute1 doesn't exist?
>> type(issue)
<class 'jira.resources.Issue'>
>> type(issue.fields)
<class 'jira.resources.PropertyHolder'>
>> type(issue.fields.parent)
<class 'jira.resources.Issue'>
>> issues[0].fields.parent.id
'12345'
>> issues[1].fields.parent.id
AttributeError: 'PropertyHolder' object has no attribute 'parent'
I want to return the list ['12345', None]
Trying to pretend the problem doesn't exist obviously returns an error :)
>> [i.fields.parent.id for i in issues]
AttributeError: 'PropertyHolder' object has no attribute 'parent'
Adding an if statement to the comprehension misses out the None value:
>> [i.fields.parent.id for i in issues if hasattr(i.fields, 'parent')]
['12345']
Using getattr with a default only returns the value of parent, not parent.id
>> [getattr(i.fields, 'parent', None) for i in issues]
[<JIRA Issue: key='PRJ-1', id='12345'>, None]
I can do it by creating a function, but six lines of code for one list comprehension seems clunky, and I have quite a few of these to do
>>> def parent_id(issue):
... if hasattr(issue.fields, 'parent'):
... return issue.fields.parent.id
... else:
... return None
>>> [parent_id(i) for i in issues]
['12345', None]
Is there a simpler / more elegant way of doing this?
You can define something that has an id attribute of None using types.SimpleNamespace, and return that from getattr instead of None.
from types import SimpleNamespace
p = SimpleNamespace(id=None)
[getattr(i.fields, 'parent', p).id for i in issues]
(p is factored out to avoid creating a new instance for every call to getattr.)
Were PEP 505 to be accepted, you could write something like
[getattr(i.fields, 'parent')?.id for i in issues]