Биоинформатика в Python: есть ли менее длинный подход к моему коду? Имеет множество операторов «если» и «за». - PullRequest
1 голос
/ 18 июня 2020
def prot_from_rf(aa_seq):
    prot1 = []
    global proteins
    for aa in aa_seq:
        if aa == "_":
            if prot1:
                for p in prot1:
                    proteins.append(p)
                prot1 = []
        else:
            if aa == "M":
                prot1.append("")
            for i in range(len(prot1)):
                prot1[i] += aa
    return proteins

Input:
MNQT_CLI_VVQLSPHLYRWISTCVNASSRRRPKRKIPCTQSPRELYTD

Output:
MNQT

Целью этого кода является сканирование аминокислотной последовательности и добавление белков, образованных между начальным и конечным кодонами, в список (белки). Prot1 - это временный список, в который начинается необработанная аминокислотная последовательность. Интересно, есть ли менее длинный подход к достижению sh того же.

Для людей, не знакомых с биологией, я беру длинную строку букв, где, если есть «М», она начинает накапливает символы, пока не достигнет «_», затем останавливается и добавляет эту новую строку в список (глобальные белки), не включая символ «_».

Ответы [ 2 ]

2 голосов
/ 19 июня 2020

Как отмечали другие, использование здесь ключевого слова global не является хорошей практикой. Вместо этого не включайте в него список proteins и расширяйте его за пределы функции.

Я бы также избегал конкатенации отдельных символов, но собирал только смещения букв «M» и использовал те, чтобы разрезать строки, как только вы дойдете до завершающего "_".

Вот как это будет выглядеть:

def prot_from_rf(aa_seq):
    result = []
    starts = []
    for i, ch in enumerate(aa_seq):
        if ch == "_":
            result.extend([aa_seq[m:i] for m in starts])
            starts = []
        elif ch == "M":
            starts.append(i)
    return result

Вызовите как:

proteins = []
# ...
proteins.extend(prot_from_rf("NMNQT_CLI_VVMQLSMPHLYR_WISTCVNAMSS"))

print(proteins)

Предыдущий ответ

Раньше мне оставалось неясным, действительно ли ваш код правильно справлялся с ситуацией, когда перед появлением «_» встречается несколько символов «M».

Если бы предполагаемое поведение было что вторая буква "M" фактически завершает последовательность (если она продолжалась) и немедленно запускает следующую, тогда вы можете использовать регулярное выражение.

import re

def prot_from_rf(aa_seq):
    return re.findall(r"M[^M_]*", aa_seq)

# Example use:
proteins = []
# ...
proteins.extend(prot_from_rf("MNQT_CLI_VVQLSPHLYRWISTCVNASSRRRPKRKIPCTQSPRELYTD"))

print(proteins)
1 голос
/ 18 июня 2020

Есть несколько вещей, которые вы можете удалить:

1) Вам не нужно объявлять proteins глобальным. Вы только добавляете, а не переназначаете, поэтому, пока он объявлен во внешней области этой функции, он будет доступен внутри вашей функции.

2) Вам не нужно проверять, prot1 пусто, так как for-l oop над пустым массивом не будет иметь никакого эффекта.

3) Это l oop может быть сокращено:

for p in prot1:
    proteins.append(p)

эквивалентно:

proteins.extend(prot1)

Это сокращает ваш код до:

def prot_from_rf(aa_seq):
    prot1 = []
    for aa in aa_seq:
        if aa == "_":
            proteins.extend(prot1)
            prot1 = []
        else:
            if aa == "M":
                prot1.append("")
            for i in range(len(prot1)):
                prot1[i] += aa
    return proteins
...