List comprehensions were the point at which Ruby lost a little of it’s shine for me and I started to think that maybe the future belonged to Python.
I’ve been discovering a few neat tricks while I’ve been working on supporting a legacy API. Here’s a few code snippets demonstrating different ways to work with lists in python.
List Comprehensions
python tips full comprehensions explanation
List comprehensions are a concise way of building sequences such as list, dictionary, set or generators. You can bypass loop constructs with a nifty one-liner (although they don’t need to be one-liners).
List comprehension:
new_list = [expression(i) for i in old_list if filter(i)]
eg:
even_list = [n for n in range(10) if n % 2 == 0]
print(even_list)
=> [0, 2, 4, 6, 8]
I’ve been using list comprehensions to recreate complex object structures from a legacy API that I need to maintain and they rarely fit on one line:
v2_object = {'artists': [{
'name': 'Bonnie Tyler',
'id': 'X1'
},
{
'name': 'Chuck Berry',
'id': 'X2'
}]
}
v1_object = {}
v1_object['names'] = [{"model": "collection.name",
"fields": {
"name": person["name"],
"id": person["id"],
"type": "person"
}
} for person in v2_object['artists']]
where
print(v1_object['names'])
=>
[
{'model': 'collection.name',
'fields': {
'name': 'Bonnie Tyler',
'id': 'X1',
'type': 'person'}
},
{'model': 'collection.name',
'fields': {
'name': 'Chuck Berry',
'id': 'X2',
'type': 'person'}
}
]
Enumerate()
enumerate() is a built-in python function that allows you to loop while maintaining an automatic counter. The counter starts at zero unless you tell it otherwise with an optional start argument.
In my examples I will show it used in conjunction with the list_comprehension from above.
v1_object['names'] = [{"model": "collection.name",
"key": count,
"fields": {
"name": person["name"],
"id": person["id"],
"type": "person"
}
} for count, person in enumerate(v2_object['artists'])]
where
print(v1_object['names'])
=>
[
{'model': 'collection.name',
'key': 0,
'fields': {
'name': 'Bonnie Tyler',
'id': 'X1',
'type': 'person'}
},
{'model': 'collection.name',
'key': 1,
'fields': {
'name': 'Chuck Berry',
'id': 'X2',
'type': 'person'}
}
]
Itertools.chain()
itertools is a module in python that has a collection of functions for iterating through lists and strings.
You need to import whichever function you want to use:
from itertools import chain
Chain takes a number of iterables (eg lists) as its arguments and combines them form a single iterable that can be looped over.
So again using the previous list comprehension. If we wanted to combine ‘artists’ and ‘managers’ in our v1_object[‘names’] we could simplify by using chain():
v2_object = {'artists': [{
'name': 'Artist 1',
'id': 'A1'
},
{
'name': 'Artist 2',
'id': 'A2'
}],
'managers': [{
'name': 'Manager 1',
'id': 'M1'
},
{
'name': 'Manager 2',
'id': 'M2'
}]
}
v1_object = {}
v1_object['names'] = [{"model": "collection.name",
"key": count,
"fields": {
"name": person["name"],
"id": person["id"],
"type": "person"
}
} for count, person in enumerate(chain(v2_object['artists'],v2_object['managers']), start=1000)]
where
print(v1_object['names'])
=>
[{'model': 'collection.name',
'key': 1000,
'fields': {'name': 'Artist 1', 'id': 'A1', 'type': 'person'}},
{'model': 'collection.name',
'key': 1001,
'fields': {'name': 'Artist 2', 'id': 'A2', 'type': 'person'}},
{'model': 'collection.name',
'key': 1002,
'fields': {'name': 'Manager 1', 'id': 'M1', 'type': 'person'}},
{'model': 'collection.name',
'key': 1003,
'fields': {'name': 'Manager 2', 'id': 'M2', 'type': 'person'}
}
]
Comments