Antipatterns advent calendar summary

This page summarizes the 24 antipatterns pages with a short description and a representative code snippet.

Scientific Python antipatterns advent calendar day one

Shows why sets are the right tool for uniqueness and fast membership checks.

import random, string

# generate 1000 random strings of 3 characters
strings = [
    ''.join(random.choices(string.ascii_lowercase, k=2))
    for _ in range(1_000)
]

Scientific Python antipatterns advent calendar day two

Explains why manual index tracking is brittle and how direct indexing solves it.

fruits = ['apple', 'banana', 'grapefruit', 'strawberry']

# get the element at index 1
fruits[1]

Scientific Python antipatterns advent calendar day three

Shows how enumerate keeps item values and indices together cleanly.

fruits = ['apple', 'banana', 'grapefruit', 'strawberry']

for fruit in fruits:
    print(fruit)

Scientific Python antipatterns advent calendar day four

Explains why overwriting built in names causes confusing bugs later.

# make a list of numbers between two limits

min = 10
max = 15

list(range(min, max))

Scientific Python antipatterns advent calendar day five

Shows why repeated string concatenation is slow and hard to read.

'Hello ' + 'world'

Scientific Python antipatterns advent calendar day six

Shows why data should live in methods rather than bare attribute containers.

class Penguin:

    # flipper length in mm, body mass in g
    def __init__(self, species, flipper_length, body_mass):
        self.species = species
        self.flipper_length = flipper_length
        self.body_mass = body_mass

Scientific Python antipatterns advent calendar day seven

Explains the right ways to iterate over dictionaries and their keys and values.

# create a dictionary
emails = {
    'Martin' : 'martin@pythonforbiologists.com', # only this one is real!
    'Jess'   : 'jessica.rodriguez@gmail.com',
    'Phil'   : 'p.smith@outlook.com'
}

# look up an email

Scientific Python antipatterns advent calendar day eight

Shows how f strings make formatting clearer than manual concatenation.

sample_id = 'abc123'

# some more code

print('Processed sample ' + sample_id)

Scientific Python antipatterns advent calendar day nine

Explains why sentinel values make APIs fragile when not needed.

def count_a(word):
    count = word.lower().count('a') # case insensitive
    return count

count_a('Apple'), count_a('banana')

Scientific Python antipatterns advent calendar day ten

Shows why error handling should use exceptions instead of print or return.

def get_domain(email_address):

    # split and take the last element of the split
    domain = email_address.split('@')[-1]
    return domain

get_domain('martin@pythonforbiologists.com'), get_domain('billgates@microsoft.com')

Scientific Python antipatterns advent calendar day eleven

Shows why manual counting is error prone and how dictionaries solve it.

string = 'banana'

letter_counts = {
    'a' : string.count('a'),
    'b' : string.count('b')
    # etc.
}

Scientific Python antipatterns advent calendar day twelve

Explains clearer ways to write conditions so logic matches intent.

fruits = [
    "apple",
    "banana",
    "orange",
    "elderberry",
    "grape",
    "pineapple",
    "apricot",

Scientific Python antipatterns advent calendar day thirteen

Shows how zip replaces manual list merging and avoids alignment bugs.

fruits = [
    "apple","banana","orange",
    "elderberry","grape",
    "olive", # technically a fruit!
]

colours = [
    'red', 'yellow', 'orange',

Scientific Python antipatterns advent calendar day fourteen

Shows why context managers are safer than manual file closing.

fruit_file = open('fruit.txt')
fruit = fruit_file.read()
fruit

Scientific Python antipatterns advent calendar day fifteen

Explains why reading whole files is risky and how to stream safely.

!head fruits.csv

Scientific Python antipatterns advent calendar day sixteen

Shows why mutating a list during iteration leads to surprises.

fruits = ["apple", "banana", "orange"]

for i, fruit in enumerate(fruits):
    fruits[i] = fruit.upper()

fruits

Scientific Python antipatterns advent calendar day seventeen

Explains robust path handling and directory traversal patterns.

import os

os.listdir('/home/martin/example_files')

Scientific Python antipatterns advent calendar day eighteen

Shows why catching broad exceptions hides real errors.

data = [
    (1,2),
    (3,0),
    (5,4)
]

Scientific Python antipatterns advent calendar day nineteen

Shows how the standard library provides common constants and helpers.

lowercase_letters = 'abcdefghijklmnopqrstuvwxyz'
uppercase_letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

Scientific Python antipatterns advent calendar day twenty

Explains how itertools covers combinations, permutations, and products.

fruits = ["apple", "banana", "orange", "mango"]

Scientific Python antipatterns advent calendar day twenty one

Shows why logging scales better than print for real workflows.

counts = {
    'apple' : 32,
    'banana' : 0,
    'strawberry': 12,
    'mango' : 0,
    # etc. etc.
}

Scientific Python antipatterns advent calendar day twenty two

Explains why dependency pinning matters for reproducible results.

import numpy as np
import pandas as pd
import seaborn as sns

data = pd.Series([1,5,3,8,4], name='values')
sns.lineplot(np.log(data), label='log values')

Scientific Python antipatterns advent calendar day twenty three

Shows when caching saves time and how to avoid repeat work.

import time

def slow_function(word):
    time.sleep(1)
    return word.lower().count('a')

Scientific Python antipatterns advent calendar day twenty four

Explains why functions should be cohesive logical units.

fruits = ['apple', 'banana', 'grapefruit','apple','mango','grapefruit']


with open('vowel_counts.csv', 'w') as output:
    for fruit in fruits:
        vowel_count = 0
        for vowel in 'aeiou':
            vowel_count += fruit.count(vowel)