November 9, 2025 at 10:16 PM EST
Migrating Python notes
November 9, 2025 at 10:16 PM EST
Migrating Python notes
This post acts as a hub for Python notes. I can’t recall the number of times I’ve had to look up pythonic concepts like kwargs, decorators or remember what _name_ == “_main_” means. When you code, be kind to yourself when writing programs and have fun testing different patterns.
# a.py
def my_function():
print("Listening to Tupac")
if __name__ == "__main__":
my_function()
print(__name__) # main
print("Song: Changes - Tupac")
# b.py
import a
my_module.my_function() # Listening to Tupac
print(my_module.__name__) # a
# It won't print "Song: Changes - Tupac"
When a module imports another, Python executes all the code at the top level. Print statements and variable assignments happen automatically, but functions only get registered unless they’re explicitly called. Basically, the “execution” means something different for functions. Below, c.py and d.py won’t give a circular import unless you call one’s play function as they’re importing.
# c.py
import d
t1 = "Change the World - Eric Clapton"
def play(tune):
print("Playing" + t1)
# d.py
import c
t2 = "Karma Chameleon - Boy Georges"
# If I uncomment the line below, I'll get a circular import
# d tries to call c's play function before it's defined
def play(tune):
print("Playing" + t2)
What are you slicing today samurai?
a[:-1]
a[:-2]
a[-1:]
a[-1:-3]
a[-3:]
What do w,x,y,z print here?
import os
path = "/home"
path2 = "User/Documents"
path3 = "/User"
w = os.path.join(path, "User/Desktop", "file.txt")
x = os.path.join(path2, "/home", "file.txt")
y = os.path.join(path, "User/public/", "Documents")
z = os.path.join(path, "Downloads","file.txt", "/home")
print(f"{w}\n{x}\n{y}\n{z}")
# Bonus: Gives the absolute path of the file
# Used in Gameok for uploading cover photos
basedir = os.path.abspath(os.path.dirname(__file__))
The default value for a here is None.
def test(a: dict | None = None) -> None:
pass
What do s1 and s2 return?
import functools
# reduce(function, iterable, initial_value)
s1 = functools.reduce(lambda x, y: x**2 + y**2, [1,2,3,4])
s2 = functools.reduce(lambda acc, y: acc + y**2, [1,2,3,4], 0)
Basics
# *: 1 layer [a,b,c]
def draw(*args):
for item in args:
print(item)
draw("Hotdog", "Scissors", "Bowl")
# **: 2 layers { a: 1, b: 2, c:3 }
def draw(**kwargs):
# kwargs is a dictionary
for key, value in kwargs.items():
print(key, value)
draw(first="Hotdog", second="Scissors")
Combined
You can specify as many arguments before *args, and ditto for **kwargs
def routines(title, *args, tempo= None, **kwargs):
print(title, args, tempo, kwargs)
routines("Deku Palace", 1, 2, 3, tempo="fast", location="Bouthiller Park")
Unpacking the stars
def formula(a, b, c):
print(a, b, c)
obj = {'b': "A", 'c': "S"}
# formula("C", b= "A", c="S")
formula("C", **obj)
elements = ["consistency", "focus"]
def truth(x, y):
print(x, y)
truth(*elements)
What does this print?
class BaseCommand:
def main(self):
print(f"Running {self.__class__.__name__}.main()")
self.invoke() # Calls subclass implementation
def invoke(self):
raise NotImplementedError("Subclasses must implement this!")
class Command(BaseCommand):
def invoke(self):
print("Executing Command.invoke()")
class Group(BaseCommand):
def invoke(self):
print("Executing Group.invoke()")
# BaseCommand().main() # Raises NotImplementedError
Command().main()
Group().main()
The function tagged with @ becomes the argument for the decorator.1. When you tag your function, the wrapper is already returned, but not called. Closures in python (inner functions) remembers the arguments from their parent functions.
def stretch_decorator(func):
# Wrapper knows that its parent stretch_decorator
# has a func argument.
def wrapper():
print("Stretch")
func()
print("Stretch")
return wrapper
# Tagging with @
# stretch_decorator(run) returns the wrapper function
@stretch_decorator
def run():
print("Run")
run()
# Output: Stretch, Run, Stretch
The order is: repeat(10) returns my_decorator(jump) which returns wrapper. The wrapper knows all the previous arguments.
def repeat(num_times):
def my_decorator(func):
def wrapper():
# Wrapper can see num_times
for i in range(num_times):
func()
return wrapper
return my_decorator
@repeat(num_times=10)
def jump():
print("Jump")
# Execute wrapper with original jump func.
jump()
Class decorator
Stretch will have access to duration.
# Play with this code as much as you want (*)
def class_decorator(cls):
# NewStretch inherits from Stretch
# Parent(Child)
class NewStretch(cls):
# cooldown is also a keyword argument
# * adding a kwarg before **kwargs
def __init__(self, *args, cooldown= "Massage your hips", **kwargs):
super().__init__(*args, **kwargs)
self.cooldown = cooldown
def duration(self, time):
print(f"Stretch {self.name} for {time} seconds")
def __str__(self):
return f"After you do {self.name}, {self.cooldown}"
return NewStretch
# class_decorator(Stretch) returns NewStretch
@class_decorator
class Stretch:
def __init__(self, name):
self.name = name
p = Stretch(name= "pigeon")
p.duration(time = 30)
print(p)
Adding properties via decorator
def add_property(cls):
@property
def area(self):
return self.width * self.height
# Why does this work?
# This inserts the area property into the class’s __dict__.
cls.area = area
return cls
@add_property
class Paper:
def __init__(self, width, height):
self.width = width
self.height = height
p = Paper(8.5, 11)
print(p.area)
# divmod
print(divmod(7, 2))
# 2D matrix for DP
dp = [[0] * (n+1) for _ in range(m+1)]
# Reverse array
arr[::-1]
# Zip (iterables)
pens = ["Fudenosuke", "Pilot Fineliner", "Staedler Pigment Liner"]
prices = [5.49, 5.34, 5.19]
print(list(zip(pens,prices)))
# Enumerate
for i, pen in enumerate(pens):
print(i,pen)
Running a module like a script using -m flag.
python -m unittest path/to/module
Testing my Chords class from tk-music
# How to run: python3 -m unittest package.tests.test_chords
import unittest
from package.src.key import Key
from package.src.chord import Chord
class TestChords(unittest.TestCase):
def setUp(self):
"""Set up a Chord instance for testing."""
key= Key("A")
self.chords = Chord(key)
def test_get_randomChords_valid(self):
self.assertEqual(self.chords.get_majorChord(), ["A", "C#/Db", "E"])
self.assertEqual(self.chords.get_minorChord(), ["A", "C", "E"])
self.assertEqual(self.chords.get_diminished_7thChord(), ["A", "C", "D#/Eb", "F#/Gb"])
self.assertEqual(self.chords.get_augmentedChord(), ["A", "C#/Db", "F"])
if __name__ == '__main__':
unittest.main()
What does this print?
import re
text = """1
a
2
bcd
3
Xyz
4
efG"""
pattern = r"(?<=\d\n)[a-z]+"
matches = re.findall(pattern, text)
print(matches)
Positive lookbehind: lowercase letters after digit + newline: [‘a’, ‘bcd’, ‘ef’] 2.
Reading about syntatic sugar.
Regex cheatsheet.
No comments on this post yet. Be the first to share your wisdom :).