Categorizing gene sequences read from a CSV file
Yeah, the problem is the switch: you have the same set of  if-elif-else conditions duplicated in two places. Chances are that as your program grows, you will add more replicas of these chains. The problem with these chains is that if later you need to add one more case in the middle, you will need to modify all replicas accordingly. This is error prone, as you might not remember all the places where you replicated the chains.

How can we deal with that better? Can we replace these chains with something else, in a way that if we add a new case in the Gene constructor, we can be free from worrying about the rest of the program? 

At least in this example, there is a workable solution. Consider these 3 lists:


refseqs = []
ensembl_genes = []
ensembl_transcripts = []



These lists are an important part of the problem. They mirror the currently supported 3 types, and when you put items in these lists, you need to refer to these lists by these names exactly.

Instead of these lists, you could use a dictionary of lists, where the keys are the gene types, and the values are lists. Something like this:

genes = dict()

with open(csv_gene_list, 'r', newline='') as csv_input:

    reader = csv.reader(csv_input, delimiter=',')
    next(reader)
    for row in reader:
        row_gene_symbol = row[0]
        row_gene_id = row[1]

        row_gene = Gene(row_gene_symbol, row_gene_id)

        if row_gene.row_gene_id not in genes:
            genes[row_gene.row_gene_id] = []

        genes[row_gene.row_gene_id].append(row_gene)
        # ...


In this form the chain is gone, and the second part of your question is naturally gone too.

As @jaime pointed out in a comment, this can be greatly simplified:


if row_gene.row_gene_id not in genes:
    genes[row_gene.row_gene_id] = []

genes[row_gene.row_gene_id].append(row_gene)



Using setdefault like this:

genes.setdefault(row_gene.row_gene_id, []).append(row_gene)