Geoinformation systems
inspired by (and partially ripped off of)
by Guido van Rossum on "The History of Python"
"[...] a Pythonic interpretation of a well-known notation for sets used by mathematicians."
"set of all $x$ such that $x > 10$"
Set of square numbers
Read "$|$" as
Thus, for this example:
Set of (all) $x^2$, such that $x \in \mathbb{N}$
or
Set of (all) $x^2$ for which $x \in \mathbb{N}$
More on this notation: https://en.wikipedia.org/wiki/Set-builder_notation
In math, the curly braces ("$\{$" and "$\}$") denote that this defines a set. Often, the predicate affirms a membership in another set.
But Python 2.0 didn't have sets. (The built-in set
type and set()
function were added with PEP 218 in Python 2.4, released 2004-11-30. Set literals of the form {1, 2, 3}
were added yet later.)
But with list comprehensions we can use a similar concept to create lists:
An itearable is anything over that you can iterate over (e.g., use it in a for
loop).
[1, 4, 9, 16, 25, 36]
[1 * 1, 2 * 2, 3 * 3, 4 * 4, 5 * 5, 6 * 6]
[x * x for x in range(1,7)]
The math example from the beginning:
(some) universal set implied (often by context)
from random import randint
s = [randint(-30, +30) for _ in range(25)]
[x for x in s if x > 10]
Squares of natural numbers whose cube is between 10 and 100
[n**2 for n in range(5) if 10 <= n**3 <= 100]
sentence = "I'm walking to the market where I'll be buying fruit"
sentence.split()
[f"I like {word}." for word in sentence.split() if word.endswith("ing")]
map()
and filter()
¶In Python 2.x:
map(f, S) == [f(x) for x in S ]
filter(P, S) == [ x for x in S if P(x)]
In general
[f(x) for x in S if P(x)]
is equivalent to
map(f, filter(P, S)) # Python 2
list( map(f, filter(P, S)) ) # Python 3
Let's find the ASCII codes of the capital letters in the following
sentence = "Guido and I are walking to the supermarket where we'll buy Spam."
map(ord, sentence)
list(_)
with
map(f, S) == [f(x) for x in S]
[ord(c) for c in sentence]
sentence
filter(str.isupper, sentence)
list(_)
with
filter(P, S) == [x for x in S if P(x)]
[c for c in sentence if str.isupper(c)]
[c for c in sentence if c.isupper()]
sentence
map(ord, filter(str.isupper, sentence))
list(_)
with
map(f, filter(P, S)) == [f(x) for x in S if P(x)]
[ord(c) for c in sentence if str.isupper(c)]
[ord(c) for c in sentence if c.isupper()]
# convert them back
''.join(map(chr, _))
Interlude
from string import printable
ascii_table = {ord(c): c for c in printable}
ascii_table
use unpacking and .items()
to access keys and values when the iterable is a dict:
inverse_ascii_table = {b: a for a, b in ascii_table.items()}
inverse_ascii_table
together with set literal syntax
{1, 2, 3}
type( {} )
set()
{i / 2 for i in [4, 6, 4, 2, 2]}
map
/filter
¶# PEP 20
# i.e.
import this
map(ord, sentence)
or
[ord(c) for c in sentence]
slight preference for map()
filter(str.isupper, sentence)
or
[c for c in sentence if c.isupper()]
slight preference for filter()
map(ord, filter(str.isupper, sentence))
or
[ord(c) for c in sentence if c.isupper()]
Flat is better than nested.
→ slight preference for list comprehension
Unless ...
... there might be a better way to un-nest it
capital_letters = filter(str.isupper, sentence)
asciii_codes = map(ord, capital_letters)
def is_vowel(chr):
return chr in 'aeiou'
filter(is_vowel, sentence)
or
filter(lambda c: c in 'aeiou', sentence)
or
[c for c in sentence if c in 'aeiou']
slight preference for list comprehension
... and when we have problems naming the functions properly when defining them
def booify(chr):
return f'B{chr}{chr}'
map(booify, sentence)
or
map(lambda c: f'B{c}{c}', sentence)
or
[f'B{c}{c}' for c in sentence]
clear preference for list comprehension
def is_vowel(chr):
return chr in 'aeiou'
def booify(chr):
return f'B{chr}{chr}'
map(booify, filter(is_vowel, sentence))
or
map(lambda c: f'B{c}{c}', filter(lambda c: c in 'aeiou', sentence))
or
[f'B{c}{c}' for c in sentence if c in 'aeiou']
very clear preference for list comprehension
def is_vowel(chr):
return chr in 'aeiou'
def booify(chr):
return f'B{chr}{chr}'
map(booify, filter(is_vowel, sentence))
So, what does this do, anyway?
list(_)
(It takes the vovels of the sentence and creates kinda baby-speach from it.)
[f'B{c}{c}' for c in sentence if c in 'aeiou']
Off course, the list comprehension does the same.