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]