Python is an experiment in how much freedom programmers need - Guido
This document captures some of the core python language contructs that will help problem solving and writing concise code. We will cover looping, iterators, generators, comprehension, and some general patterns for programming simple problems. We will also ponder some of the most useful standard library classes and functions.
Things like modules, packages, async, threading, etc., are not covered.
Reader is advised to treat this post as a crash course on basic Python. The reader is assumed to have a little prior programming knowledge.
Types: bool, int, float, string
Sequences: list, tuple, set, dict
Collections: deque, heapq, defaultdict, namedcollection
Iteration is a novel feature of Python's containers (list, tuples, dicts etc.,) and generators. Let us see some of the most used operations on iterables.
# Looping (a.k.a Iteration)
>>> s = [1, 2, 3, 4, 5]
>>> for v in s:
... print(v, end=" ")
1 2 3 4 5
# Variable unpacking
>>> s = (1, 2, 3)
>>> x, y, z = s
>>> y
2
>>> x, *extra = s
>>> extra
[2, 3]
# Membership
>>> s = [1, 2, 3, 4, 5]
>>> 5 in s
True
>>> 4 not in s
False
A variety of python built-in functions accept iterables as input.
Notable ones are
min, max, sum, any, all, sorted, reversed
>>> s = [1, 2, 2, 3, -4, 50, 6, 7, 8, 9, 9, 0]
>>> tuple(s)
(1, 2, 2, 3, -4, 50, 6, 7, 8, 9, 9, 0)
>>> set(s)
{0, 1, 2, 3, 6, 7, 8, 9, 50, -4}
>>> min(s), max(s), any(s), all(s), sum(s)
(-4, 50, True, False, 93)
>>> sorted(s) # rer
[-4, 0, 1, 2, 2, 3, 6, 7, 8, 9, 9, 50]
# s is NOT modified by any of the above operations
>>> s
[1, 2, 2, 3, -4, 50, 6, 7, 8, 9, 9, 0]
Operations on sequence (s)
>>> # Concatenation
>>> s = (1, 2, 3)
>>> r = (4, 5, 6)
>>> s + r
(1, 2, 3, 4, 5, 6)
>>> # Making copies
>>> s = [1, 2, 3]
>>> s * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
Indexing and Slicing
s[i] => Element at index 'i'. First index is '0'
s[i:j] => elements from index 'i' upto 'j'.
(not including j). total of 'j-i' elements.
s[i:j:stride] => elements s[i], s[i+stride], s[i+2*stride]
... until index j is reached.
s[:i] => first 'i' elements
s[j:] => elements from j onwards. last "len(s) - j" elements.
s[::2] => elements at even indices
s[::-1] => reversed copy of s
>>> s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> s[:4]
[1, 2, 3, 4]
>>> s[1:4]
[2, 3, 4]
>>> s[1:]
[2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> s[::2]
[1, 3, 5, 7, 9]
>>> s[::-1]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Range loop
for i in range(len(s)):
...
Enumeration
for i, v in enumerate(s):
...
Loop till s
is NOT empty
while s:
...
Looping in dict d
for k, v in d.items():
...
for k in d.keys():
...
for v in d.values():
...
>>> s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> for i in range(len(s)):
... print((i, s[i]), end=" ")
(0, 1) (1, 2) (2, 3) (3, 4) (4, 5) (5, 6) (6, 7) (7, 8) (8, 9) (9, 10)
>>>
>>> for i, v in enumerate(s): print((i,v), end=" ")
...
(0, 1) (1, 2) (2, 3) (3, 4) (4, 5) (5, 6) (6, 7) (7, 8) (8, 9) (9, 10)
>>>
Use comprehension to transform a collection of data into another data structure.
For example, taking all the items in a list, applying an operation, and creating a new list:
nums = [1, 2, 3, 4, 5]
squared = [ n * n for n in nums ]
It is also possible to apply a filter for transformation
nums = [1, 2, 3, 4, 5]
squared = [ n * n for n in nums if n % 2 == 0]
General syntax for list comprehension. sets and dict comprehension has similar syntax
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN ]
>>> stocks = [
... {'name': 'PYPL', 'shares': 100, 'price': 91.1 },
... {'name': 'MSFT', 'shares': 50, 'price': 123.67 },
... {'name': 'AAPL', 'shares': 75, 'price': 340.51 },
... {'name': 'AMZN', 'shares': 60, 'price': 1667.89 },
... {'name': 'XOM', 'shares': 200, 'price': 95.25 }
... ]
>>>
# Collect all stock names
>>> names = [s['name'] for s in stocks]
['PYPL', 'MSFT', 'AAPL', 'AMZN', 'XOM']
# Entries with atleast 100 shares
>>> atleast100 = [s['name'] for s in stocks if s['shares'] >= 100 ]
['PYPL', 'XOM']
# Total shares*price
>>> total = sum([s['shares']*s['price'] for s in stocks])
159955.15000000002
# Collect (name, shares) tuples
>>> ns = [ (s['name'], s['shares']) for s in stocks ]
[('PYPL', 100), ('MSFT', 50), ('AAPL', 75), ('AMZN', 60), ('XOM', 200)]
# Set comprehension
>>> names = { s['name'] for s in portfolio }
{'PYPL', 'AMZN', 'AAPL', 'MSFT', 'XOM'}
# Dict comprehension
>>> ns = { s['name']:s['price'] for s in stocks }
{'PYPL': 91.1,'MSFT': 123.67,'AAPL': 340.51,'AMZN': 1667.89,'XOM': 95.25}
nums = [1, 2, 3, 4]
squares = (x * x for x in nums)
>>> nums = [1,2,3,4,5]
>>> nums
[1, 2, 3, 4, 5]
>>> squares = ( n * n for n in nums)
>>> squares
<generator object <genexpr> at 0x100558580>
A generator object that produces the values on demand via iteration, lazily. ```"yield" is the magic keyword.
>>> def countdown(n):
... print('Counting down from', n)
... while n > 0:
... yield n
... n -= 1
...
>>> for x in countdown(5):
... print('yielding ', x)
...
Counting down from 5
yielding 5
yielding 4
yielding 3
yielding 2
yielding 1
>>> c = countdown(100)
>>> c
<generator object countdown at 0x1004e2740>
>>>
>>> next(c)
Counting down from 100
100
>>> next(c)
99
>>> next(c)
98
Strings are first-class objects in Python. They are immutable sequences of characters. Any operation on a string produces a new immutable string.
s = "pythonic"
for c in s:
print(c)
Some of the most useful string methods: find, lower, upper, split, strip, endswith, startswith
Functions and Lambda Expressions
Functions are the building blocks for Python programs, defined with def
keyword.
# Euclid's GCD algorithm
def gcd(m,n):
r = m % n
if r == 0:
return n
return gcd(n, r)
An anonymous function can be defined using a lambda expression:
lambda args: expression
'args' is a comma-separated list of arguments, and expression is an expression involving those arguments. Here’s an example:
a = lambda x, y: x + y
equivalent to
def add_lambda(x, y): return x + y
but, consise without a name. Useful in many in many instances, where we have to pass functions.