Python concepts
February 13, 2020
Dieter Devlaminck
Overview ● Python functions (functional
programming)
● Python data structures
● Python iterators
● Best practices on dates/times and strings
Programming paradigms
class Circle():
PI = 3.14159265359
def __init__(self, radius):
● Object-oriented programming: self.radius =
○ everything is an object (an instantiation of a class) radius
○ the class defines the methods that can be called on an object
○ a class can have attributes that hold data for a specific object
● def area(self):
Functional programming:
○ the output of a function only depends on the input arguments (not return
on some global state) PI*(self.radius**2)
○ functions don’t change state, no side-effects def circle_area(radius, PI):
return PI*(radius**2)
Python has some features to use a functional style of programming
Python functions are first-class objects
Functions as first-class objects:
● you can assign them to a variable (without the function actually being called)
● pass a function as argument to other functions
● return a function from another function
Anonymous lambda function
Anonymous functions are very simple functions that contain only one expression and which are typical
assigned to a variable (representing a function handle)
multiply = lambda a, b: a*b
print(multiply(10, 3))
>>>30
Passing functions to other functions
In Python functions can easily be passed to another function just like any other variable is passed
def print_decoration(function):
print(“result of function“)
result = function()
print(result)
add = lambda a, b: a+b
print_decoration(add(3,5))
>>>result of function
>>>8
Sorting elements of an iterable
integer_list = [1, 7, 3, 9, 11, 4, 0, 3]
sorted(integer_list)
>>>[0, 1, 3, 3, 4, 7, 9, 11]
sorted(integer_list, reverse=True)
>>>[11, 9, 7, 4, 3, 3, 1, 0]
Sorting
list_of_tuples = [(‘a’,1), (‘b’, 7) , (‘c’,3), (‘d’,9), (‘e’,11), (‘f’,4), (‘g’,0), (‘h’,3)]
Sort the list according to the second element of the tuple
sorted(list_of_tuples, key=lambda x: x[1])
>>>[(‘g’,0), (‘a’,1), (‘c’,3), (‘h’,3), (‘f’,4), (‘b’, 7), (‘d’,9), (‘e’,11)]
Sorting
list_of_dicts = [{“id”:1, “name”: “C”}, {“id”:2, “name”: “A”}, {“id”:3, “name”: “B”}, {“id”:4, “name”: “D”}]
Sort the list according to the name value in the dictionaries
sorted(list_of_tuples, key=lambda x: x[“name”])
>>>[{“id”:2, “name”: “A”}, {“id”:3, “name”: “B”}, {“id”:1, “name”: “C”}, {“id”:4, “name”: “D”}]
Multilevel sorting
To sort elements according to more than one key, let the key function return a tuple. It will first sort by
the value of the first field, then the value of the second field etc.
list_of_tuples = [('a',3), ('b', 9) , ('c',3), ('d',9), ('e',11), ('f',4), ('g',11), ('h',3)]
sorted_list = sorted(list_of_tuples, key=lambda x: (x[1], x[0]))
[('a', 3), ('c', 3), ('h', 3), ('f', 4), ('b', 9), ('d', 9), ('e', 11), ('g', 11)]
Partial functions
It’s a way to pass some of the arguments to the function without calling it yet with all its parameters
def multiply(a, b):
return a*b
partial_multiply = partial(multiply, b=10)
print(partial_multiply(2))
>>>20
print(partial_multiply(7))
>>>70
Collections: defaultdict
An extension of the regular dict where you can provide a function that will be called to initialize the
value of a missing key
Example:
Initialize every key’s value with a zero
dd = collections.defaultdict(int) #equivalent to collections.defaultdict(lambda: 0)
dd["A"] += 10
d = dict()
d[“A”] += 10 #raises a KeyError
Collections: defaultdict
The provided function should not take any arguments
dd = collections.defaultdict(list)
dd["A"].extend([10,20])
print(dd)
{“A”: [10, 20] }
Collections: Counter
Similar to defaultdict(int)
c = collections.Counter()
c[“A”] += 10
print(c)
{“A”: 10}
Map the elements of an iterable
Transform the elements of an iterable by applying the specified function
Extract the name from all the dictionaries and transform the names to lowercase
list_of_dicts = [{“id”:1, “name”: “C”}, {“id”:2, “name”: “A”}, {“id”:3, “name”: “B”}, {“id”:4, “name”: “D”}]
[i for i in map(lambda x: x["name"].lower(), list_of_dicts)]
>>>['c', 'a', 'b', 'd']
Itertools: zip
Iterating over multiple lists simultaneously
list1 = [‘a’, ‘b’, ‘c’, ‘d’]
list2 = [1, 2, 3, 4]
for i, j in itertools.zip(list1, list2):
print(i, j)
Consecutively prints the tuples (‘a’,1), (‘b’,2), (‘c’,3) and (‘d’,4)
Itertools: combinations
lst = [0,1,2,3,4]
for tpl in itertools.combinations(lst, 3):
print(tpl) Generate all possible 3-size tuples of the elements
in the iterator respecting the properties below
(0, 1, 2)
(0, 1, 3) Combinations:
(0, 1, 4)
● order doesn’t matter, but the function sorts
(0, 2, 3)
(0, 2, 4) the elements
● no repetitions
(0, 3, 4)
(1, 2, 3)
(1, 2, 4)
(1, 3, 4)
(2, 3, 4)
Itertools: permutations
lst = [0,1,2]
for tpl in itertools.permutations(lst,3):
print(tpl) Generate all 3-size tuples of the elements in the
iterator (here n=3)
(0, 1, 2)
(0, 2, 1) Permutations:
(1, 0, 2)
● Order is important
(1, 2, 0)
● No repetitions
(2, 0, 1)
(2, 1, 0)
One-line dot-product
https://docs.python.org/3.8/library/itertools.html for more information on iterators
x = [1,2,3]
y = [10,10,10]
sum(map(operator.mul, x, y))
Unicode
A way to uniquely represent all symbols (across all natural languages) using code point (i.e. a number)
Text in files is typically byte encoded (binary representation) in a specific format, e.g. UTF-8, latin1…
When reading from a file one can specify it’s encoding (default UTF-8) and Python will decode it into
Unicode
Before writing Unicode strings to a database or file, it’s best to again specify an encoding
open('unicode.txt', encoding='utf-8')
Software should only work with Unicode strings internally, decoding the input data as soon as possible
and encoding the output only at the end
source: https://docs.python.org/3/howto/unicode.html
Dates and times
import pytz
date_string = "01-01-2019 18:30:10"
brussels_tz = pytz.timezone("Europe/Brussels")
utc_tz = pytz.timezone("UTC")
dt = datetime.strptime(date_string, "%d-%m-%Y %H:%M:%S")
localized_dt = brussels_tz.localize(dt)
>>>datetime.datetime(2019, 1, 1, 18, 30, 10, tzinfo=<DstTzInfo 'Europe/Brussels' CET+1:00:00 STD>)
utc_dt = localized_dt.astimezone(utc_tz)
>>>datetime.datetime(2019, 1, 1, 17, 30, 10, tzinfo=<UTC>)
If possible it’s best to internally use UTC in your software and output the results in the desired timezone