Python has a few functional programming tools: Lambda functions and the three higher-order functions map, filter and reduce. I'll explain them now and I'll give some usage examples.
lambda
A lambda creates an anonymous function, that means a function without a name. A lambda may have any number of arguments.
Here are some examples for lambdas:
f = lambda x: x * x
print(f(7))
Output: 49
g = lambda x, y: x + y * y + abs(x)
print(g(1, 1), g(1, -1), g(-1, 1), g(10, 6), g(-10, 6))
Output: (3, 3, 1, 56, 36)
h = lambda myVar, anotherVar: set([myVar, anotherVar])
print(h(1, 2), h("a", 1), h("a", "a"), h(1, 1))
Output: (set([1, 2]), set(['a', 1]), set(['a']), set([1]))
Sometimes you would like to get an if-statement in a lambda. So imagine you would like to make a lambda function like this:
def f(x):
if x == 0:
return 42
elif x == 1:
return 1337
else:
return 0
This is the way you would do it:
f = lambda x: x == 0 and 42 or x == 1 and 1337 or 0
(Thanks to Ikke's blog for the hint!)
map(function, sequence)
Map is a function with two parameters. The first parameter is another function, the second is a sequence. Map returns a list. It only applies function to every item of the sequence.
Here are some examples:
def square(x):
return x * x
l = map(square, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
l = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
This is equivalent to:
l = map(lambda x: x * x, range(1, 11))
You can also use more than one list:
a = range(-10, 10)
b = range(0, 20)
l = map(lambda x, y: x * y, a, b)
Output: [0, -9, -16, -21, -24, -25, -24, -21, -16, -9, 0, 11, 24, 39, 56, 75, 96, 119, 144, 171]
reduce(function, sequence)
You can quite often reduce problems to an operation on two elements. Reduce takes two elements from sequence, uses function on them and saves the result. Then it takes the result and another element of the sequence and uses function...
Example: Imagine you would like to get the sum of a list. Then you need to add two elements of the list, save the result and add another element, save the result, add another element, ...
r = reduce(lambda x, y: x + y, [1, 2, 63, 3, 5])
r = 74
You can calculate the factorial n! like this:
fac = lambda n: reduce(lambda x, y: x * y, range(1, n + 1))
print(fac(2))
print(fac(3))
print(fac(10))
Output: 2 6 3628800
filter(function, sequence)
filter gets all elements from sequence, where function returns true:
def is_prime(element):
if element == 2:
return True
elif element <= 1 or element % 2 == 0:
return False
else:
for i in range(3, element, 2):
if element % i == 0:
return False
return True
my_list = [4, 4, 9, 12, 13, 2, 7, 9, 11, 11]
r = filter(is_prime, my_list)
r = [13, 2, 7, 11, 11]
Some more examples
Task: What is the sum of digits of \(2^n, n \in \mathbb{N}\)?
sumOfDigits = lambda exp: reduce(
lambda x, y: x + y, map(lambda x: int(x), str(2 ** exp))
)
print(sumOfDigits(2))
print(sumOfDigits(3))
print(sumOfDigits(4))
print(sumOfDigits(10000))
Output: 4 8 7 13561
Task: Encode and decode a string in the following way: Split Words by spaces. Every plaintext character gets a two-digit numerical representation in base 16. A is 01, B is 02 and Z is 1A.
# Thanks to lebenf: http://stackoverflow.com/a/3226719/562769
chunks = lambda l, n: [l[x : x + n] for x in range(0, len(l), n)]
decodeWord = lambda s: "".join(map(lambda x: chr(int(x, 16) + 64), chunks(s, 2)))
decode = lambda s: " ".join(map(decodeWord, s.split(" ")))
encodeWord = lambda p: "".join(map(lambda x: "%.2X" % (ord(x) - 64), p))
encode = lambda p: " ".join(map(encodeWord, p.split(" ")))
cipher = encode("HELLO WORLD")
print("Cipher Text: %s" % cipher)
print("Plain Text: %s" % decode(cipher))
See also
- Wikipedia:
- Python-Kurs: Lambda, filter, reduce und map (German)