
8 January 2026
| Data Type | Mutable | Ex | Desc |
|---|---|---|---|
int | ❌ No | 5 | Whole numbers |
float | ❌ No | 5.5 | Decimal numbers |
str | ❌ No | "Hi" | Text characters |
list | ✅ Yes | [1, 2] | Ordered collection |
tuple | ❌ No | (1, 2) | Fixed ordered collection |
dict | ✅ Yes | {"a": 1} | Key-value pairs |
bool | ❌ No | True | Logic (True/False) |
set | ✅ Yes | {1, 2} | Unique items only |
Python is dynamically typed language
With Final the type checker will flag any attempts to change the value as an error
from typing import Final
NAME: Final[str] = 'dat'
x = 5
x = x + 1You didn't change the number 5 into 6. Instead:
Python created an object 5 and pointed x at it.
When you added 1, Python created a brand new object 6.
Python moved the name tag x from the 5 object to the 6 object.
The object 5 remains unchanged (and is eventually cleaned up if nothing else points to it).
Python slices follow the [start:stop] pattern, where the start is included and the stop is excluded.
| Slice | Translation | Resulting Indexes |
|---|---|---|
[1:3] | Start at 1, stop before 3 | 1, 2 |
[:2] | Start at 0, stop before 2 | 0, 1 |
[2:] | Start at 2, go to the end | 2, 3, ... |
[:] | Copy the whole list | All indexes |
| Syntax | Start (Inclusive) | End (Exclusive) | Resulting Sequence |
|---|---|---|---|
data[0:3] | ✅ | ❌ | Indexes 0, 1, 2 |
range(0, 3) | ✅ | ❌ | Numbers 0, 1, 2 |
randrange(0, 3) | ✅ | ❌ | Possible: 0, 1, 2 |
randint(0, 3) | ✅ | ✅ | Possible: 0, 1, 2, 3 |
Ordered, mutable, allow duplicate
colors = ["red", "green", "blue"]append() to add item at end, insert() to add item at specified index
extend() use to append a list with iterable objects (lists, tupe, set, dict)
s1 = {7,8,9}
l1 = [1,2,3]
t1 = (4,5,6)
d1 = {'99': [1,2,3]}
l1.extend(s1)
l1.extend(t1)
l1.extend(d1)
print(l1) # [1, 2, 3, 8, 9, 7, 4, 5, 6, '99']remove(item), pop(index) if you do not specify the index, pop the last
del() remove the variable while clear() clearing items
Shallow copy
l1 = [1,2,3]
l2 = l1
l2.append(4)
print(l1) #[1,2,3,4]Copy a list: copy( ), list( ), l1[ : ]
Use * to repeating list or tuple
l2 = l1 * 2List unpacking
colors = ["red", "green", "blue"]
r, g, b = colorsList comprehension
newlist = [expression for item in iterable if condition == True]
l1 = [1,2,3]
l2 = [x for x in l1]
print(l2) # [1,2,3]Ordered, immutable
location = (40.7, 74.0)Ordered, mutable but the keys must be immuatable, value can be any
user = {"name": "A", "age": 22}Unordered, mutable, can only contain unique and immutable items, fast for lookup (use in)
my_set = {1, 9, 22, '1', '3'}add() add item to set (only immutable)
update() add iterable object (tuples, lists, dictionaries, string) to set
set.update(mydict.items()) will add as tuple
To remove use remove() or discard() (will NOT raise an error)
When use pop(), you do not know which item that gets removed.
Set operators
Intersection &: Returns elements common to both sets.
{1, 2} & {2, 3} → {2}Union |: Returns all unique elements from both sets.
{1, 2} | {2, 3} → {1, 2, 3}Difference -: Returns elements in the first set but not the second.
{1, 2} - {2, 3} → {1}Symmetric Difference ^: Returns elements in either set, but not both.
{1, 2} ^ {2, 3} → {1, 3}It combining assignment and evaluation in a single step
# With walrus operator
if (value := input("Enter a number: ")):
print(f'You entered {value}')Iterable: An object that can be looped over (e.g., in a for loop) or passed to the built-in iter() function to get an iterator. Lists, tuples, sets, dict, string, and range objects are iterables.
Iterator: An object that maintains its state during iteration and can be advanced using the built-in next() and iter() function. Once an iterator is exhausted (all its values have been returned), it cannot be reused
range() is an iterable, but it is not an iterator
r = range(5)
next(r)
TypeError: 'range' object is not an iteratorr = range(3)
i1 = iter(r)
next(i1) # 0
next(i1) # 1
i2 = iter(r) # Create a new iterator from the same range
next(i2) # 0 (i2 starts from the beginning)
next(i1) # 2 (i1 continues where it left off)As specified in the PEP 8 style guide, is snake_case (lowercase with words separated by underscores)
Are the methods starting and ending with double underscores '__' such as
cbr = Vehicle() # __init__()
print(cbr) # __str__()
print(repr(crb)) # __repr__()Is an object that guarantees the setup and teardown of resources, even if errors occur during execution
The most common way to use a context manager is with the with statement, which automatically handles the necessary "enter" and "exit" steps.
# Using a context manager (recommended)
with open('some_file.txt', 'w') as f:
f.write('Hola!')
# The file is automatically closed when the 'with' block is exited*args accept number of positional arguments.
def my_function(*args):
print(typeof(args)) # tuple
my_function("Emil", "Tobias", "Linus") **kwargs accept number of keyword arguments
def my_function(**kwargs):
print(typeof(kwargs)) # dict
my_function(fname = "Tobias", lname = "Refsnes") def my_function(title, *args, **kwargs):
print("Title:", title)
print("Positional arguments:", args)
print("Keyword arguments:", kwargs)
my_function("User Info", "Emil", "Tobias", age = 25, city = "Oslo") def my_function(a, b, c):
return a + b + c
numbers = [1, 2, 3]
result = my_function(*numbers) # Same as: my_function(1, 2, 3)
print(result) def my_function(fname, lname):
print("Hello", fname, lname)
person = {"fname": "Emil", "lname": "Refsnes"}
my_function(**person) # Same as: my_function(fname="Emil", lname="Refsnes") *and ** in function definitions to collect arguments, and use them in function calls to unpack arguments
Decorators add extra behavior to a function, without changing the function's code.
A decorator is a function that takes another function as input and returns a new function.
def my_decorator(func):
"""
A simple decorator
"""
def wrapper(*args, **kwargs):
print('before func call')
result = func(*args, **kwargs)
print('after func call')
return result
return wrapper
@my_decorator
def greeting():
print("Hello")
# greeting = my_decorator(greeting)
greeting()user = {
'name' : 'dat',
'coins' : 3
}
print(("{name} has {coins} coins left").format(**user))
print(f"{user['name']} has {user['coins']} coins left")Lambda functions are commonly used with built-in functions like map(), filter(), sorted() and reduce().
numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
print(doubled) # [2, 4, 6]numbers = [1, 2, 3, 4, 5, 6, 7, 8]
odd_numbers = list(filter(lambda x: x % 2 != 0, numbers))
print(odd_numbers) # [1, 3, 5, 7]
colors = ["red", "green", "blue"]
char_count = reduce(lambda prev, curr: prev + len(curr), colors, 0)
from functools import reduce
sorted_words = sorted(colors, key=lambda x: len(x))class Vehicle:
color = 'red' # class property
def __init__(self, name = 'Honda'):
self.name = name # instance property
def __str__(self): # to_string function
return f"{self.name} {self.color}"
cbr = Vehicle('cbr')
print(cbr.name)del used to delete object or properties of object
class Student(Person):
def __init__(self, fname, lname):
#add properties etc.__init__() function overrides the inheritance of the parent's __init__() function.
To keep init function from the parent
Person.__init__(self, fname, lname)
super().__init__(fname, lname) In Python, you can make properties/ methods private by using a double underscore __ prefix, for protected use a single underscore _ prefix:
class Person:
def __init__(self, name, age, salary):
self.name = name
self.__age = age # Private property
self._salary = salary # Protected property
p1 = Person("Emil", 25)
print(p1.name)
print(p1.__age) # This will cause an error When add = sign, Python defaults to using the repr() representation of that object
name = 'dat'
print(f'{name = }') # name = datUse .nf where n is the number of decimal points.
{3.14159:.2f} 3.14Use , to add thousands separators.
{1000000:,} 1,000,000Use % to multiply by 100 and add a percent sign
{0.25:.1%} 25.0%now: datetime = datetime.now()
date_format = '%d/%m/%y'
print(f'{now:{date_format}}')Convert an object into a string using a specific method
!s: Calls str() on the value.
!r: Calls repr() on the value (often used for debugging).
!a: Calls ascii() on the value
print(f"{object!r}")Left Align <: {var:<10} aligns text to the left in a 10-character field.
Right Align >: {var:>10} aligns text to the right.
Center Align ^:{var:^10} centers the text.
Padding: Adding a character before the alignment symbol fills the empty space.
{var:*^10} centers the variable and pads it with *.A class that with some concept
Symbolic Names: Enums use meaningful, descriptive names (conventionally in UPPER_CASE).
Constants, Unique: Members defined within an enum are unique and constant.
Type-Safety: Enums preventing errors from typos.
from enum import Enum
class Color(Enum):
Red = 'R'
Green = 'G'
Blue = 'B'
print(Color('R')) # Color.Red
print(Color.Red) # Color.Red
print(repr(Color.Red)) # <Color.Red: 'R'>
print(Color.Red.value) # R
print(Color.Red.name) # RedMake with
by Nguyen Huu Dat
© 2025