HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Genotype as input, give the phenotype

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thegenotypegiveinputphenotype

Problem

I want to write a Python script where the input is a genotype (e.g. "CCDd") based upon the following Punnett square. The output should be the phenotype (e.g. "seal").

My code works, but doesn't look that 'pythonic' at all.

def colour(input):

    if len(set(input)) == 2 and input[0] != 'C' and input[2] != 'D':
        return('lilac')
    elif len(set(input[2::])) == 1 and input[2] != 'D':
        return('blue')
    elif len(set(input[0:2])) == 1 and input[0] != 'C':
        return('chocolate')
    else:
        return('seal')

Solution

You correctly identified that you need to count the number of lowercase c and d. But using a set to do so is not the right tool. Instead, I suggest using collections.Counter:

from collections import Counter

def color(genotype):
    assert len(genotype) == 4

    count = Counter(genotype)
    blue = count['d'] == 2
    chocolate = count['c'] == 2

    if blue and chocolate:
        return 'lilac'
    if blue:
        return 'blue'
    if chocolate:
        return 'chocolate'
    return 'seal'


I also added a debug check to ensure that the length of the input sequence is always four.

Given the mini debate that occured in the comments, pertaining to variable names, you may consider this slight variation:

from collections import Counter

def color(genotype):
    assert len(genotype) == 4

    count = Counter(genotype)
    recessive_traits = [count[gene] == 2 for gene in 'cd']

    if all(recessive_traits):
        return 'lilac'
    if recessive_traits[0]:
        return 'blue'
    if recessive_traits[1]:
        return 'chocolate'
    return 'seal'


It may be more expressive as to what you're testing, and why.

Code Snippets

from collections import Counter


def color(genotype):
    assert len(genotype) == 4

    count = Counter(genotype)
    blue = count['d'] == 2
    chocolate = count['c'] == 2

    if blue and chocolate:
        return 'lilac'
    if blue:
        return 'blue'
    if chocolate:
        return 'chocolate'
    return 'seal'
from collections import Counter


def color(genotype):
    assert len(genotype) == 4

    count = Counter(genotype)
    recessive_traits = [count[gene] == 2 for gene in 'cd']

    if all(recessive_traits):
        return 'lilac'
    if recessive_traits[0]:
        return 'blue'
    if recessive_traits[1]:
        return 'chocolate'
    return 'seal'

Context

StackExchange Code Review Q#148813, answer score: 6

Revisions (0)

No revisions yet.