- Learning Python as a language
- Intro
- Syntax
- Mutability, identity, conversion, representation
- Boolean logic
- Operations on strings
- Containers
- Lists
- Loops
- Dict
- Set
- Function
- Exceptions
- OOP and classes (introduction)
- Imports and modules
- Files
- Typing Python
- Scopes, assignment and pass by reference/value
- Python is fully dynamic and everything is an object
- The standard library
- Navigating the Python documentation
- Python "gotchas"
- What's next?
- Self-review
- References
- Indentation and spacing are syntax in Python
- Python favours shorter, explicit name
s.upper()
(Python) vs.s.toUpperCase()
(JS)
- Python has very few keywords and constructs. E.g. no
switch
, nodo... while
.
❓ Questions to ask orally:
- How do you display something?
print
- How do you get some input?
input("yes or no?")
- What are the base types?
int
,float
,bool
,str
,bytes
,complex
- What are the container types?
list
(literal:[]
),tuple
(()
),dict
({"key": "value"}
),set
({1, 2, 3}
),frozenset
.
- How do you assign a variable?
a = 1
,a = b = 1
,a += 1
- How do you write a conditional statement?
if... else
❓ Questions to ask orally:
- What are mutable and immutable types in Python?
- What is the difference between equality and identity?
- How do you convert between types?
- How do you display the value of a name?
Most types are immutable. list
, set
and dict
are mutable.
id(obj)
returns the object's memory address==
compares equalityis
compares identity- Type conversion: just use the type itself e.g.
int("2")
- Representation:
repr("a")
,repr([1, 2, 3])
More information:
# How do you compare numbers?
x > 1
# How do you check for truthiness?
bool(True)
# ternary operator
ternary = "a" if v else "b"
# or, and, not?
❓ Questions to ask orally:
- How do you check if a string starts with something?
- Is all alphabetical characters?
- How do you join a list with a string?
s.startswith(value)
s.endswith(value)
s.find(sub, start, end)
s.isalpha(), s.islower()
s.upper(), s.lower()
# join
s.join(sequence)
assert ", ".join([1, 2]) == "1, 2"
❓ Questions to ask orally:
- How do you
print
a variable within a string?
Formatting:
name = "Toaster"
print(f"Hello {name}")
❓ Questions to ask orally:
- How do you get the length of a container?
- How do you get the minimum of a list?
- How do you return
True
if all values within a container are truthy?
len
, min
, sorted
, enumerate
, zip
, all
, any
, reversed
# You can mix types
l = ["a", 1]
# Presence check with "in"
v = "a" in ["a"]
assert v is True
Comprehensions:
# List
r = [i ** 2 for i in range(10) if i % 3]
# Generator
r = (i ** 2 for i in range(10) if i % 3)
# Dict
r = {v: v * 2 for f in range(10)}
❓ Questions to ask orally:
- How do you append to a list?
- How do you get the last item in a list?
- How do you get the last 3 items in a list?
Operation on lists: l.append
, l.extend
, l.insert(index, val)
, l.remove(val)
, l.pop([index])
, l.sort()
(in place), l.reverse()
v = list([1, 2])
# literals are preferred
v = [1, 2]
# Sequence containers indexing: l[start slide:end slide:step]
# -1 works as you would expect
❓ Questions to ask orally:
- How do you count from 1 to 10?
- Sequence:
range([start], end, step)
- Sequence:
for i in range(10):
print(i)
for item in [0, 2, 4]:
print(item)
# What will this loop do?
while v == True:
v = False
# continue
# break
❓ Questions to ask orally:
- How do you write a dict?
- How do you add a key and value to a dict?
- How do you access a dict key?
- How do you check of a key in a dict?
- How do you get a value in a dict or a default if it's not there?
# Definition
value = 1
c = dict(key=value)
# literal is preferred
c = {"key": value}
# Access
assert c["key"] == 1
# Deletion
del c["key"]
# Assignment
c["key"] = 1
d.keys()
d.values()
d.items()
d.pop(key, default)
d.popitem() # (key, value)
d.get(key, default)
d.setdefault(key, default)
# How do you define a set?
s = {1, 2, 3}
# How do you get the union of a set with another?
s |= {1, 2}
# Intersection
s &= {1, 2}
# ~ difference
# < <= > >= inclusion relations
s.update(s2)
s.copy()
s.add(value)
s.remove(value)
s.pop()
❓ Questions to ask orally:
- How do you define a function?
- How do you define a function with mandatory arguments?
- How do you define a function with optional arguments?
- What happens when mandatory arguments are not provided?
def hello():
"""Say hello."""
print("hello world")
help(hello)
# arguments
def hello(name: str):
print(f"Hello {name}")
# Both work!
hello("Louis")
hello(name="Louis")
# arguments are required in Python! No default null or undefined
# Optional argument:
def hello(name: str = "toaster"):
print(f"Hello {name}")
# x, y, z are positional arguments
# args are the rest positional arguments (list)
# a, b are keyword arguments
# kwargs are the rest keyword arguments (dict)
# def hello(x, y, z, *args, *, a=1, b="2", **kwargs):
# pass
❓ Questions to ask orally:
- Are there anonymous functions?
- Not really.
lambda
is not supposed to be assigned and only supports a single line
- How do you transform a list in positional arguments?
f(*args)
- How do you transform a dict in keyword arguments?
f(**kwargs)
c = map(lambda v: v + "a", ["b", "c"])
assert c == ["ba", "ca"]
See also:
❓ Questions to ask orally:
- How do you try something?
- How do you create a custom exception?
# Simple try... except... with raise
try:
raise ValueError("Wrong value")
except ValueError:
print("caught ValueError")
try:
raise ValueError("e")
except ValueError as e:
print(e)
else:
print("no exception")
finally:
print("always run")
# Custom exception
class MyException(Exception):
pass
❓ Questions to ask orally:
- When are classes created? Runtime or compile time?
- What are instances?
- What are class attributes vs. instance attributes?
- What are class methods vs. instance methods?
Classes are created at runtime and can be modified at runtime.
-
Class = type
-
Class instance = object
-
Class can have class attributes and class methods
-
Instance have attributes and methods defined on the class
-
super()
-
Multiple inheritance (e.g. mixins)
-
isinstance
,issubclass
class Toaster:
pass
❓ Questions to ask orally:
- How do you define a class?
- How do you define a constructor?
- How do you define a method? A classmethod?
- How do you define a class variable?
class Toaster:
"""A toaster."""
brand = "Moulinex"
def say_hello(self):
return "hello bread!"
print(Toaster)
print(Toaster.brand)
print(Toaster.say_hello)
print(Toaster.__doc__)
# Let's create a new instance
toaster = Toaster()
print(toaster.brand)
print(toaster.say_hello)
print(toaster.say_hello())
❓ Questions to ask orally:
- How do you create a class instance?
- How do you assign instance attributes?
class Toaster:
brand = "Moulinex"
def __init__(self, color: str) -> None:
self.color = color
def say_color(self) -> None:
return f"hello my color is {self.color}"
t = Toaster("red")
print(t.color)
print(t.say_color)
print(t.say_color())
# Attribute change
t.color = "green"
say_color = t.say_color
# It works! (poke JavaScript)
say_color()
t2 = Toaster("blue")
assert t.brand == t2.brand
assert t.color != t2.color
# Watch out when using mutable variables as class variable
- There are no private methods or private attribute. Prefix with
_
(preferred) or__
to state that this should not be accessed.
class BetterToaster:
def __init__(self, color: str, brand: str) -> None:
self.color = color
self._brand = brand
self._is_toasting = False
def start_toasting(self) -> None:
self._is_toasting = True
def toast(self) -> None:
self.color = "red"
self.start_toasting()
# Custom getter
@property
def status(self) -> str:
return "on" if self._is_toasting else "off"
t = BetterToaster("red", "moulinex")
t.toast()
assert t.status == "on"
❓ Questions to ask orally:
- How do you inherit?
- Does Python support multiple inheritance?
class Animal:
pass
class Dog(Animal):
pass
class GoldenRetriever(Dog):
pass
olympe = GoldenRetriever()
assert isinstance(olympe, Dog)
assert isinstance(olympe, Animal)
assert issubclass(GoldenRetriever, Dog)
assert issubclass(GoldenRetriever, Animal)
# Multiple inheritance
class HasName:
pass
class DogPet(Dog, HasName):
pass
https://docs.python.org/3/tutorial/classes.html
❓ Questions to ask orally:
- How do you group functionality in Python?
- How do you import and export?
from module import x
import x
❓ Questions to ask orally:
- How do you export stuff in Python?
- You don't! Everything is exported by default.
- Should you use relative or absolute imports?
❓ Questions to ask orally:
- What can go wrong when not using
with
?
f = open("file.md")
content = f.read()
f.close()
# Better: using "context" with "with"
with open("file.md", "w") as f:
f.write("# Hello")
import json
with open("file.json") as f:
content = json.load(f)
# That's it!
❓ Questions to ask orally:
- Is Python weakly typed?
- Is Python statically typed?
Important points:
- Types are always optional.
- Types are not checked at runtime, only if you use a tool like
mypy
.
a: str = "a"
v: list[str] = [a]
c: dict[str, int] = {a: 1} # {"a": 1}
def get_double(i: int) -> int:
return i * 2
❓ Questions to ask orally:
- What is a namespace?
- When are they created?
A namespace is a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries, but that’s normally not noticeable in any way (except for performance), and it may change in the future. Examples of namespaces are: the set of built-in names (containing functions such as abs(), and built-in exception names); the global names in a module; and the local names in a function invocation. In a sense the set of attributes of an object also form a namespace. The important thing to know about namespaces is that there is absolutely no relation between names in different namespaces; for instance, two different modules may both define a function maximize without confusion — users of the modules must prefix it with the module name.
https://docs.python.org/3/tutorial/classes.html
- Namespaces are created at different moments and have different lifetimes.
❓ Questions to ask orally:
- What is a scope?
A scope is a textual region of a Python program where a namespace is directly accessible. “Directly accessible” here means that an unqualified reference to a name attempts to find the name in the namespace.
- Assignment
x = 1
- Imports
import sys
- Function definition
def func(): pass
- Function parameters
def func(a): pass
- Class definition
class Toaster: pass
Some other ways:
- Container comprehension
- Exception block
- Classes and instances
A special quirk of Python is that – if no global or nonlocal statement is in effect – assignments to names always go into the innermost scope. Assignments do not copy data — they just bind names to objects.
❓ Questions to ask orally:
- Where does Python look for references?
Python looks for a reference in this order:
- Local (or function) scope
- A scope is created for each run, not at function definition
- True even if you call the function recursively
locals()
- Enclosing (or nonlocal) scope
- Names of the enclosing function for nested function definition
- Global (or module) scope
- Top-level scope
- Formatted
UPPER_CASE_WITH_UNDERSCORE
globals()
- Builtin
- E.g.
dir
,open
,len
, etc. dir(__builtins__)
- E.g.
Questions:
- When inside a function, where does Python look at?
- When outside a function, where does Python look at?
FIRST_NAME = "Louis"
def say_hello(last_name: str) -> None:
def say(message: str) -> None:
print(f"{message} {name}")
say(f"Hello {FIRST_NAME}")
say_hello("de Funès")
❓ Questions to ask orally:
- How do you write a global var?
In Python, you can't modify global
or nonlocal
variables without being explicit about it:
NAME = "Louis"
def func():
# This creates a new name in the local scope
NAME = "Claude"
func()
# NAME did not change
assert NAME == "Louis"
You need to use the global
or nonlocal
keyword when you want to write globals:
NAME = "Louis"
def func():
global NAME
NAME = "Claude"
func()
# Now it works!
assert NAME == "Claude"
For more information:
- Python Scope & the LEGB Rule: Resolving Names in Your Code
- Pass by Reference in Python: Background and Best Practices
- https://docs.python.org/3/tutorial/classes.html
# a is the name, 2 is the value
# the name "a" is bound to the value 2
a = 2
# the name a is rebound to the value 3
a = 3
# Python keeps track of how many names are bound to a value
class Toaster:
pass
t = Toaster()
t2 = t
from sys import getrefcount
assert getrefcount(t) > 2
def modify_dict(d):
d["a"] = None
the_dict = {"b": 1}
return_value = modify_dict(the_dict)
print(return_value)
print(the_dict)
# To avoid modifying:
def modify_dict(d):
d = d.copy()
d["a"] = None
❓ Questions to ask orally:
- Is a class an object?
- Is a function an object?
- Is an exception an object?
- Is a module an object?
class Toaster:
def __init__(self, color: str):
self.color = color
t = Toaster("red")
dir(t)
vars(t)
# You can get a dict of local variables!
locals()
globals()
# Classes are objects!
Toaster.__name__
dir(Toaster)
def hello(t: Toaster) -> None:
print(f"Hello {t.color}")
# Functions are objects!
hello.__name__
hello.__doc__
dir(hello)
# Modules are objects!
import sys
dir(sys)
# Exception are objects!
try:
raise ValueError("hello")
except ValueError as e:
print(e)
dir(e)
# You can return class and function just like any other object
def get_class_and_function():
def func():
return 1
class MyClass:
pass
return func, MyClass
# ImportError can happen anywhere and can be caught
try:
import toaster
except ImportError:
toaster = None
# You can programmatically import
import importlib
toaster = importlib.import_module("toaster")
See also:
See:
- builtin vs. standard lib
- Mutable default arguments
- Circular module dependencies
- Clashes with builtin naming (e.g.
id
) - String identity
- Identity (
is
) vs. equality (==
) - Late binding closures
- Tuple by default
a = "b",
sort
vs.sorted
Next course: Python style
See my course on advanced Python.
- Context (
with
) - Iterators
- Generators
- Operator overloading
- Magic methods
- Descriptors
- Properties
- Decorators
- Useful builtin packages:
dataclasses
- Walrus (
:=
) operator is not
(a single binary operator) vs.is (not ...)
(is
andnot
are separated)
❓ Questions to ask orally:
- What are the base types?
- What are the container types?
- How do you get the length of a list?
- How do you check if a key is in a dict?
- How do you get a value from a dict? Even if it's not there?
- How do you iterate over a dict's
key, value
in afor
loop? - How do you coerce as a string? As a boolean?
- How can you write a switch in Python?
dict
if... elif... else
- What's the difference between equality and identity? What are the operators?
- How do you count from 1 to 10?
- How do you type a function?
- How do function arguments work?
- How do you write a class? With a constructor? With a class method? With inheritance?
- How do you export a function from a module?
- In what sense can we say that Python is a dynamic language?