使用数字列表的Python子集序列

时间:2017-10-18 22:37:26

标签: python for-loop substring

我正在尝试编写一个程序,该程序接受一个包含数字列表的文件,并使用这些数字中的每一个来对字符串的一部分进行子集化。当我尝试调用我的函数时(下面)我收到错误:

TypeError: unsupported operand type(s) for -: 'str' and 'int'

我尝试将for循环中的i更改为int(i),以防由于某种原因,i不是整数但导致以下错误:< / p>

ValueError: invalid literal for int() with base 10: ''

代码:

#Function Collects Sequences and Writes to a Files
def gen_insertion_seq(index, seq, gene):
    output = open("%s_insertion_seq.txt" % gene, 'w')
    indices = index.read()
    sequence = seq.read()
    for i in indices:
        site = sequence[i-9:i+15]
        output.write(site + '\n')

#Open Index Files
shaker_index = open("212_index.txt")
kir2_index = open("214_index.txt")
asic1a_index = open("216_index.txt")
nachra7_index = open("252_index.txt")

#Open Sequence Files
shaker_seq = open("212_seq.txt")
kir2_seq = open("214_seq.txt")
asic1a_seq = open("216_seq.txt")
nachra7_seq = open("252_seq.txt")
#Call function on Index and Sequence Files - Should output list of generated Sequences for insertion sites.
#Must hand check first couple
gen_insertion_seq(shaker_index, shaker_seq, 'shaker')

示例输入文件:

212_index.txt

1312
210
633
696
1475
637
1198
645
1504
361
651
...

212_seq.txt

ATGGCCGCCGTGGCACTGCGAGAACAACAGCTCCAACGAAATAGTCTGGATGGATACGGTTCACTGCCTAAACTGTCTAGCCAAGACGAAGAAGGTGGCGCCGGCCATGGCTTCGGTGGGGGC

2 个答案:

答案 0 :(得分:0)

代码中的错误是由于read没有达到您预期的效果所致。 Called without parameters,它将整个文件读入一个字符串。然后迭代字符串中的字符而不是文件中的数字。当您在序列的索引中执行'1' - 9时,会发生TypeError

您将迭代值转换为int的直觉基本上是正确的。但是,由于您仍然在迭代字符,因此您会获得int('1')int('3')int('1')int('2'),然后是来自int('\n')的{​​{3}} 。 read按原样读取整个文件,新行和所有文件。

幸运的是,文件中的行ValueErrorfile object。这意味着您可以执行for line in file: ...之类的操作,line将采用您要解析的每个索引的字符串值。它还有额外的好处,就是可以从行中删除行结尾,这意味着您可以将其直接传递到int而不需要进一步修改。例如。

您可以对代码进行许多其他改进,包括使其正常工作的更正。

  1. 根据@ Acccumulation的建议,在iterable块中打开文件,以确保在程序崩溃时正确清理它们,例如来自I / O错误。当块结束时它也会自动关闭文件,这是你目前根本没有做的事情(但应该是)

  2. 从概念上讲,根本不需要传递文件对象。您只能在一个地方使用每一个用于一个目的。我甚至会扩展这一点,建议您编写一个小函数来将每种文件类型解析为可用格式,然后传递它。

  3. 文件可在Python中按行迭代。这对于索引文件尤其方便,索引文件是一种非常面向行的格式。您根本不需要完整read,并且可以从@MaximTitarenko的评论中节省几个步骤。

  4. 您可以直接在文件上使用with来合并任何包含换行符的序列。

  5. 结合所有建议,您可以执行以下操作:

    def read_indices(fname):
        with open(fname, 'r') as file:
            return [int(index) for index in file]
    
    def read_sequence(fname):
        with open(fname, 'r') as file:
            return ''.join(file)
    

    由于文件是字符串的可迭代,您可以在str.join中使用它们,也可以使用字符串连接操作。您的其余代码现在看起来会更清晰:

    def gen_insertion_seq(index, seq, gene):
        indices = read_indices(index)
        sequence = read_sequence(seq)
        with open("%s_insertion_seq.txt" % gene, 'w') as output:
            for i in indices:
                site = sequence[i-9:i+15]
                output.write(site + '\n')
    
    gen_insertion_seq('212_index.txt', '212_seq.txt', 'shaker')
    gen_insertion_seq('214_index.txt', '214_seq.txt', 'kir2')
    gen_insertion_seq('216_index.txt', '216_seq.txt', 'asic1a')
    gen_insertion_seq('252_index.txt', '252_seq.txt', 'nachra7')
    

    您的主要功能现在更容易理解,因为它只关注序列而不关注I / O和解析等内容。你也没有一堆打开的文件句柄,等待错误。事实上,文件操作都是自包含的,远离真正的任务。

    如果您有文件ID和基因名称的序列(list comprehensions),您可以通过循环进一步简化对函数的调用:

    for id, gene in zip((212, 214, 216, 252), ('shaker', 'kir2', 'asic1a', 'nachra7')):
        gen_insertion_seq('%d_index.txt' % id, '%d_seq.txt' % id, gene)
    

    PS。 Python教程中的in the Python sense部分非常好。关于I/O的部分可能是您特别感兴趣的。

答案 1 :(得分:-3)

尝试使用双引号'shaker'输入"shaker"。或者,在你的函数中使用str(gene)。

好的,我刚刚意识到它是python所以引用的东西不应该重要,我想

open("{}_insertion_seq.txt".format(gene), 'w')

如果是在写,请更改output.write(site + '\n')output.write(str(site) + '\n')