Skip to content

Data Structures

Python provides four built-in data structures that you will use constantly in bioinformatics. Lists store ordered sequences. Tuples store fixed records. Dictionaries map keys to values. Sets track unique items. This page covers each one with examples drawn from genomics.

A list is an ordered, mutable collection. You create one with square brackets. Lists are ideal for storing gene names, read counts, or any sequence of values.

gene_names = ["TP53", "BRCA1", "EGFR", "KRAS", "MYC"]
print(gene_names)
['TP53', 'BRCA1', 'EGFR', 'KRAS', 'MYC']

Use len() to check how many items a list contains.

print(len(gene_names))
5

Python uses zero-based indexing. The first element is at index 0.

print(gene_names[0])
TP53

Negative indices count from the end. Index -1 gives you the last element.

print(gene_names[-1])
MYC

Slicing extracts a sublist. The start index is included. The stop index is excluded.

print(gene_names[1:3])
['BRCA1', 'EGFR']

Use .append() to add an item to the end of a list.

gene_names.append("PTEN")
print(gene_names)
['TP53', 'BRCA1', 'EGFR', 'KRAS', 'MYC', 'PTEN']

Use .remove() to delete the first occurrence of a specific value.

gene_names.remove("KRAS")
print(gene_names)
['TP53', 'BRCA1', 'EGFR', 'MYC', 'PTEN']

A list comprehension builds a new list by transforming each item in an existing list. This is a common pattern for processing expression data. Here we log-transform raw counts.

import math
counts = [100, 250, 50, 300, 75]
log_counts = [math.log2(c + 1) for c in counts]
print(log_counts)
[6.658211482751795, 7.971543553950772, 5.672425341971495, 8.233619676759702, 6.247927513443585]

You can also filter with a condition. This extracts only significant p-values.

pvalues = [0.001, 0.23, 0.04, 0.87, 0.005]
significant = [p for p in pvalues if p < 0.05]
print(significant)
[0.001, 0.04, 0.005]

A tuple is like a list, but it cannot be changed after creation. This makes tuples useful for storing fixed records like a gene’s chromosomal location.

gene_location = ("BRCA1", "chr17", 43044295)
print(gene_location)
('BRCA1', 'chr17', 43044295)

You access elements by index, just like a list.

print(gene_location[0])
BRCA1

Tuple unpacking lets you assign each element to a separate variable in one line.

gene, chrom, pos = gene_location
print(f"{gene} is at {chrom}:{pos}")
BRCA1 is at chr17:43044295

A dictionary maps keys to values. Think of it as a lookup table. In bioinformatics, you might map gene names to expression levels.

gene_expression = {
"TP53": 23.5,
"BRCA1": 45.2,
"EGFR": 12.8,
"KRAS": 67.3,
}
print(gene_expression)
{'TP53': 23.5, 'BRCA1': 45.2, 'EGFR': 12.8, 'KRAS': 67.3}

Access a value by its key.

print(gene_expression["BRCA1"])
45.2

Add a new entry by assigning to a new key.

gene_expression["MYC"] = 34.1
print(gene_expression)
{'TP53': 23.5, 'BRCA1': 45.2, 'EGFR': 12.8, 'KRAS': 67.3, 'MYC': 34.1}

Use .keys() and .values() to extract all keys or all values.

print(list(gene_expression.keys()))
['TP53', 'BRCA1', 'EGFR', 'KRAS', 'MYC']
print(list(gene_expression.values()))
[23.5, 45.2, 12.8, 67.3, 34.1]

Use .get() to look up a key with a default value. This avoids a KeyError when the key is missing.

print(gene_expression.get("PTEN", 0.0))
0.0

The .items() method returns each key-value pair. This is the standard way to loop over a dictionary.

for gene, expr in gene_expression.items():
print(f"{gene}: {expr}")
TP53: 23.5
BRCA1: 45.2
EGFR: 12.8
KRAS: 67.3
MYC: 34.1

A set is an unordered collection of unique items. Sets are powerful for comparing gene lists. For example, you can find overlapping genes between an experiment and a known pathway.

upregulated = {"TP53", "EGFR", "MYC", "PTEN"}
pathway_genes = {"TP53", "BRCA1", "EGFR", "RB1"}
overlap = upregulated & pathway_genes
print(overlap)
{'TP53', 'EGFR'}

The - operator finds items in the first set that are not in the second.

only_up = upregulated - pathway_genes
print(only_up)
{'PTEN', 'MYC'}

The | operator combines both sets into one.

all_genes = upregulated | pathway_genes
print(all_genes)
{'BRCA1', 'MYC', 'PTEN', 'TP53', 'EGFR', 'RB1'}

Converting a list to a set removes duplicates. Convert back to a list if you need list behavior. Use sorted() for consistent ordering.

gene_list = ["TP53", "BRCA1", "TP53", "EGFR", "BRCA1", "TP53"]
unique_genes = list(set(gene_list))
print(sorted(unique_genes))
['BRCA1', 'EGFR', 'TP53']

You can nest data structures inside each other. A dictionary of dictionaries is a natural way to store sample metadata.

samples = {
"S1": {"condition": "control", "read_count": 25000000},
"S2": {"condition": "treated", "read_count": 31000000},
}
print(samples["S1"]["condition"])
control
print(samples["S2"]["read_count"])
31000000

Chain the keys to reach deeper values. The first key selects the sample. The second key selects the field.

Structure Syntax Ordered Mutable Duplicates Use case
List [a, b, c] Yes Yes Yes Gene lists, expression values
Tuple (a, b, c) Yes No Yes Fixed records, coordinates
Dictionary {k: v} Yes* Yes Keys: No Lookup tables, sample metadata
Set {a, b, c} No Yes No Unique genes, overlap analysis

*Dictionaries preserve insertion order in Python 3.7 and later.

You now know the four core data structures in Python. Next, learn how to control program flow with conditionals and loops in Control Flow.