I'm just fiddling with a simulation of (Mendel's First Law of Inheritance).
Before i can let the critters mate and analyze the outcome, the population has to be generated, i.e., a list has to be filled with varying numbers of three different types of tuples without unpacking them.
While trying to get familiar with itertools (I'll need combinations later in the mating part), I came up with the following solution:
import itertools
k = 2
m = 3
n = 4
hd = ('A', 'A') # homozygous dominant
het = ('A', 'a') # heterozygous
hr = ('a', 'a') # homozygous recessive
fhd = itertools.repeat(hd, k)
fhet = itertools.repeat(het, m)
fhr = itertools.repeat(hr, n)
population = [x for x in fhd] + [x for x in fhet] + [x for x in fhr]
which would result in:
[('A', 'A'), ('A', 'A'), ('A', 'a'), ('A', 'a'), ('A', 'a'), ('A', 'a'), ('A', 'a'), ('A', 'a'), ('A', 'a')]
Is there a more reasonable, pythonic or memory saving way to build the final list, e.g. without generating the lists of for the three types of individuals first?
You could use itertools.chain
to combine the iterators:
population = list(itertools.chain(fhd, fhet, fhr))
Though I would say there's no need to use itertools.repeat
when you could simply do [hd] * k
. Indeed, I would approach this simulation as follows:
pops = (20, 30, 44)
alleles = (('A', 'A'), ('A', 'a'), ('a', 'a'))
population = [a for n, a in zip(pops, alleles) for _ in range(n)]
or perhaps
allele_freqs = ((20, ('A', 'A')),
(30, ('A', 'a')),
(44, ('a', 'a')))
population = [a for n, a in allele_freqs for _ in range(n)]