Morris-Frank

projects tutorials cv hire me

Collection of Python snippets

On-going list of niche snippets for programming Python like an annoying know-it-all (also some actual good tips).


Python

Use underscores in numbers

Underscores in numbers are ignored, but can increase readability:

2_000_000 == 2000000

Use underscores to discard returns

Use underscores to ignore return elemens. More advanced, use can use a wildcard * to discard a sub-set of the return arguments:

def some_function():
    
    return a, b, c, d

a, _, c, d = func()
a, *_, d = func()

Check for any of list of types

if isinstance(variable, (int, float)):
    # …

Use default if is None

Instead of:

def func(var = None):
    if var is None:
        var = "DEFAULT"

you can do:

def func(var = None):
    var = var or "DEFAULT"

Use type in add_argument to directly transform input

A pattern I use a lot in ArgumentParser is to abuse the type argument. As the input argument is just casted by calling the type object you can also just give a function to transform the input. For example a config file:

from argparse import ArgumentParser
import json

parser = ArgumentParser()
parser.add_argument("--config", type=lambda x: json.load(open(x, 'r')))
args = parser.parse_args()

args.config # is now the loaded config file already!

Unpack namespace as keyword arguments

Assume you have an argument parser that matches the arguments of the main function and just want them put in:

from argparse import ArgumentParser

def main(file: str, name: str):
    pass

parser = ArgumentParser()
parser.add_argument("--file")
parser.add_argument("--name")

with vars you can make the Namespace a dict and unpack it in one statement:

main(**vars(parser.parse_args()))

Implicit infinite defaultdict

Lets say you want to set

dictionary["level1"]["level2"]["arg"]["attr"] = some_value

without having to define any of the levels. Make a infinite defaultdict:

from collections import defaultdict

infinite_defaultdict = defaultdict(lambda: infinite_defaultdict)
dictionary = infinite_defaultdict()

dictionary["level1"]["level2"]["arg"]["attr"] = some_value

global vs nonlocal

Use the keyword nonlocal to access the index variable in the outer function but not the global variable which you would access with global.

index = 0

def outer_function():
    index = 42
    def inner_fucntion():
        nonlocal index
        index += 1
    inner_function()

Using slash with pathlib Paths

The / operator is overloaded for pathlib so you can easily extend paths:

from pathlib import Path

path = Path("/home/morris")
code_path = path / "code"

code_path == Path("/home/morris/code")

Iterate over only folders in a folder

from pathlib import Path

for folder in filter(Path.is_dir, Path(path).iterdir()):
    pass

Use product to reduce nested for loops

# instead of
for i in range(N):
    for j in range(N):
        pass

# you can do
from itertools import product
for i, j in product(range(N), range(N)):
    pass

Generate a random list of words

import random

def random_words(n: int) -> list[str]:
    return random.sample(open("/usr/share/dict/words").read().splitlines(), n)
def some_function():
    some_function.attribure =