首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从CSV文件中读取的基因序列的分类

从CSV文件中读取的基因序列的分类
EN

Code Review用户
提问于 2015-12-04 23:13:26
回答 3查看 190关注 0票数 6

我对编程还比较陌生,我很想得到一些关于我的代码的以下部分的反馈。

代码语言:javascript
复制
class Gene:
    def __init__(self, gene_symbol, gene_id):
        # gene_symbol represents the abbreviated name of the gene (string)
        # Example: 'RHO' (short for 'Rhodopsin')
        self.gene_symbol = gene_symbol

        # gene_id represents an accession ID for the gene (string)
        # Example: 'NM_000539.3'
        self.gene_id = gene_id

        # is_valid_ functions check if the type of the gene_id is valid
        # and returns True or False
        # Assume that the types of the gene_id are mutually exclusive
        if is_valid_refseq(gene_id):
            # Example of a valid refseq: 'NM_000539.3'
            self.gene_id_type = REFSEQ

        elif is_valid_ensembl_gene(gene_id):
            # Example of a valid ensembl_gene: 'ENSG00000163914'
            self.gene_id_type = ENSEMBL_GENE

        elif is_valid_ensembl_transcript(gene_id):
            # Example of a valid ensembl_transcript: 'ENST00000296271'
            self.gene_id_type = ENSEMBL_TRANSCRIPT

        else:
            raise InvalidGeneIDError("Invalid gene_id: {}".format(gene_id))



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

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.gene_id_type == REFSEQ:
            refseqs.append(row_gene)

        elif row_gene.gene_id_type == ENSEMBL_GENE:
            ensembl_genes.append(row_gene)

        elif row_gene.gene_id_type == ENSEMBL_TRANSCRIPT:
            ensembl_transcripts.append(row_gene)

        else:
            # What do I do here?
            raise AssertionError('Unrecognized gene_id_type: {}'.format(
                    row_gene.gene_id_type))

假设gene_symbolgene_id是字符串,is_valid_函数是在代码的其他地方实现的。

我想问一下,实现这些多个if - the语句是否是正确的方法。我觉得如果在行后添加更多的这些条件表达式,我的代码可能会变得杂乱无章。

另一个问题是关于最后一条else语句。在这种情况下我该怎么办?如果代码按预期工作,那么它不应该到达最后一个else语句,因为在初始化Gene对象时应该引发InvalidGeneIDError。一种解决方案是省略这一部分并将elif row_gene.gene_id_type == ENSEMBL_TRANSCRIPT:更改为else:,但我更愿意明确地说明具体的检查,以帮助传达代码的意图。

在我前进的过程中,我的主要任务是集中精力开发良好的编码风格/习惯,并编写可读的代码。我还想学习/发现Python必须提供的新工具/技巧。如有任何建议和帮助,将不胜感激。

EN

回答 3

Code Review用户

发布于 2015-12-04 23:55:56

是的,问题在于切换:在两个地方都有相同的if-elif- set条件重复。很可能,随着程序的发展,您将添加更多的这些链的副本。这些链的问题是,如果以后需要在中间再添加一种情况,则需要相应地修改所有副本。这很容易出错,因为您可能不记得复制链的所有位置。

我们怎样才能更好地处理这件事?我们是否可以用其他的方法来替换这些链,如果我们在Gene构造函数中添加一个新的情况,我们就可以不用担心程序的其余部分了?

至少在这个例子中,有一个可行的解决方案。考虑这3份清单:

参= [] ensembl_genes = [] ensembl_transcripts = []

这些清单是问题的一个重要部分。它们反映了当前支持的3种类型,当您将项目放入这些列表中时,需要准确地通过这些名称引用这些列表。

您可以使用列表字典来代替这些列表,其中键是基因类型,值是列表。就像这样:

代码语言:javascript
复制
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)
        # ...

在这种形式下,链条消失了,你问题的第二部分自然也消失了。

正如@jaime在评论中指出的,这可以大大简化:

如果基因中没有row_gene.row_gene_id:划_gene.row_基因_id= [] 划_gene.row_基因_id.append(Row_gene)

像这样使用setdefault

代码语言:javascript
复制
genes.setdefault(row_gene.row_gene_id, []).append(row_gene)
票数 4
EN

Code Review用户

发布于 2015-12-05 00:51:02

以下是我的代码在采纳@janos的建议后的一个修订版。

代码语言:javascript
复制
# Make an empty dictionary that will hold the following key-value pairs
# {gene_id_type: list of Gene objects}
all_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)
        gene_id_type = row_gene.gene_id_type

        # Check if gene_id_type is in the dictionary
        if gene_id_type in all_genes:
            # Append row_gene to the list in the dictionary
            all_genes[gene_id_type].append(row_gene)

        else:
            # Make a new key named gene_id_type and
            # assign its value as a list with row_gene in it
            all_genes[gene_id_type] = [row_gene]

# Do stuff with all_genes
票数 0
EN

Code Review用户

发布于 2015-12-07 12:20:17

如果文件中的行只包含两个元素,则可以同时设置符号和id。我也不认为你需要有row_前缀。

代码语言:javascript
复制
gene_symbol, gene_id = row

这将将每个row解压到gene_symbolgene_id的两个值中。这是一种同时获得两个值的更干净的方法。如果row有两个以上的值,则会引发错误,但这也意味着您不会忽略格式错误的数据。

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/112942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档