Skip to content

Instantly share code, notes, and snippets.

@prabhakhar
Created May 2, 2024 15:14
Show Gist options
  • Save prabhakhar/26a0f67783f891e791b7e7016b353ff3 to your computer and use it in GitHub Desktop.
Save prabhakhar/26a0f67783f891e791b7e7016b353ff3 to your computer and use it in GitHub Desktop.

Python Essentials

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.

https://xkcd.com/353/

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.

Basics

Types: bool, int, float, string Sequences: list, tuple, set, dict Collections: deque, heapq, defaultdict, namedcollection

Iterables

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]

Sequences

A sequence is an iterable container that has a size and allows items to accessed by integer index starting at 0. For ex., ```string, list, tuple are sequences.

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]

Looping

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)
>>>

Comprehension

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}

Generators

Same as a list comprehension, but produces the result iteratively. The syntax is the same as for list comprehensions except that parentheses are used instead of square brackets.
    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

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

Miscellaneous

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.

Decorators

Classes

Collections

Deque
Heap
Counter
Defaultdict

Python Object Model

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment