Functions
Functions let you wrap reusable logic into a single named block. You define a function once and call it many times. This keeps your code organized and reduces copy/paste errors.
Writing functions
Section titled “Writing functions”Basic function
Section titled “Basic function”Use the def keyword followed by a name and parameters. The return statement sends a value back to the caller.
def calculate_gc_content(sequence): """Calculates the GC content of a DNA sequence.
Args: sequence: A string of DNA bases.
Returns: The fraction of G and C bases in the sequence. """ sequence = sequence.upper() gc_count = sequence.count("G") + sequence.count("C") return gc_count / len(sequence)
print(calculate_gc_content("ATGCGATCGA"))0.5print(calculate_gc_content("AAATTTAAATTT"))0.0The triple-quoted string right after def is called a docstring. It describes what the function does. We use the Google style for docstrings throughout this project. More on that below.
Default arguments
Section titled “Default arguments”You can give parameters default values. The caller can override them or leave them as is.
def label_significance(pvalue, log2fc, alpha=0.05, fc_threshold=1.0): """Labels a gene as up, down, or not significant.
Args: pvalue: The p-value from a statistical test. log2fc: The log2 fold change. alpha: Significance threshold. Defaults to 0.05. fc_threshold: Minimum absolute fold change. Defaults to 1.0.
Returns: A string label: "up", "down", or "ns". """ if pvalue < alpha and log2fc > fc_threshold: return "up" elif pvalue < alpha and log2fc < -fc_threshold: return "down" else: return "ns"
print(label_significance(0.001, 2.5))upprint(label_significance(0.001, -1.8))downprint(label_significance(0.5, 3.0))nsYou can override defaults by name. This makes function calls easier to read.
print(label_significance(0.001, 0.5, fc_threshold=0.25))upReturning multiple values
Section titled “Returning multiple values”A function can return several values at once using a tuple. You unpack them into separate variables on the calling side.
def summarize_counts(counts): """Summarizes a list of gene counts.
Args: counts: A list of integer read counts.
Returns: A tuple of (total, mean, nonzero_count, zero_fraction). """ total = sum(counts) mean_val = total / len(counts) nonzero = sum(1 for c in counts if c > 0) zero_fraction = sum(1 for c in counts if c == 0) / len(counts) return total, mean_val, nonzero, zero_fraction
gene_counts = [0, 15, 230, 0, 45, 120, 0, 78]total, mean_val, nonzero, zero_frac = summarize_counts(gene_counts)print(f"Total: {total}")print(f"Mean: {mean_val}")print(f"Nonzero genes: {nonzero}")print(f"Zero fraction: {zero_frac}")Total: 488Mean: 61.0Nonzero genes: 5Zero fraction: 0.375Variables created inside a function are local. They do not affect variables with the same name outside the function.
threshold = 0.05
def check_significance(pvalue): threshold = 0.01 return pvalue < threshold
print(check_significance(0.03))print(f"Global threshold: {threshold}")FalseGlobal threshold: 0.05The function uses its own local threshold of 0.01. The global threshold stays at 0.05. Keep this in mind when debugging unexpected behavior.
Lambda functions
Section titled “Lambda functions”A lambda is a small anonymous function written on one line. It is useful for short operations you only need once.
genes = ["TP53", "BRCA1", "EGFR", "KRAS", "MYC"]sorted_by_length = sorted(genes, key=lambda g: len(g))print(sorted_by_length)['MYC', 'TP53', 'EGFR', 'KRAS', 'BRCA1']Use lambdas for simple sorting or filtering. For anything longer than one expression, write a regular function instead.
map and filter
Section titled “map and filter”map applies a function to every item in a list. filter keeps only items that pass a test.
import mathcounts = [100, 250, 50, 300, 75]log_counts = list(map(lambda c: round(math.log2(c + 1), 2), counts))print(log_counts)[6.66, 7.97, 5.67, 8.23, 6.25]pvalues = [0.001, 0.23, 0.04, 0.87, 0.005]significant = list(filter(lambda p: p < 0.05, pvalues))print(significant)[0.001, 0.04, 0.005]Both map and filter return iterators. Wrap them in list() to see the results. You can also achieve the same results with list comprehensions, which many Python programmers prefer for readability.
A note on docstrings
Section titled “A note on docstrings”This project uses Google-style docstrings as the standard format. Every function you write should include one. Google-style docstrings use Args:, Returns:, and Raises: sections with indented descriptions beneath each heading.
This format works with documentation generators like Sphinx and its Napoleon extension. These tools can parse your docstrings and produce professional HTML documentation automatically. Writing good docstrings is a habit that pays off when your codebase grows.
Quick reference
Section titled “Quick reference”| Concept | Syntax | Example |
|---|---|---|
| Define a function | def name(params): |
def gc(seq): |
| Default argument | param=value |
alpha=0.05 |
| Return a value | return value |
return gc_count / length |
| Return multiple values | return a, b, c |
return total, mean, zeros |
| Lambda | lambda params: expr |
lambda g: len(g) |
| Map | map(func, iterable) |
map(lambda c: c+1, counts) |
| Filter | filter(func, iterable) |
filter(lambda p: p<0.05, pvals) |
| Docstring | """...""" after def |
See examples above |
Next steps
Section titled “Next steps”Now that you can write your own functions, learn how to use code others have written. Head to Working with Packages to learn about importing and managing Python libraries.