Conversation
CaptnClementine
left a comment
There was a problem hiding this comment.
Чуть-чуть запутались в сложной теме с асбтрактным классом. Все остальное сделано очень хорошо, и получилось возвращать нужного типа при транскрипции, и освоили super (что мне показалось очень сложным!). Тут хочется добавить про вот такую фишку: можно в классе NucleicAcidSequence задать переменные, которые у классов уже должны быть. Но не задавать их значения. вот так:
def init(self, sequence: str, alphabet: dict = None, complement_alphabet: dict = None):
self.sequence = None
self.alphabet = None
self.complement_alphabet = None
Тут может возникнуть вопрос, а как же тогда мы обратимся к алфавиту, если он None. А тут и кроется секрет - можно создать отдельный сеттер для создания экзмепляров дочернего класса
Вот такое прописываем в родительском нуклеотидном классе
def setter(self, sequence: str, alphabet: dict, complement_alphabet: dict = None):
self.sequence = sequence
self.alphabet = alphabet
self.complement_alphabet = complement_alphabet
А в дочернем, например РНК - вызываем его уже с алфавитом, заданном в РНК:
def init(self, sequence: str):
super().setter(sequence, ALPHABET, REV_TRANSCRTPTION_COMPLEMENT)
Так получится хранить каждый нужный алфавит в своем классе.
Хорошая работа!
| @@ -0,0 +1,88 @@ | |||
| class BiologicalSequence: | |||
| def __init__(self, sequence): | |||
| self.sequence = sequence | |||
There was a problem hiding this comment.
Суть абстрактного класса - не держать в себе готовые атрибуты и методы, а только говорить какие атрибуты и/или методы должны обязательно быть у его наследников. Здесь выходит так, что у наследуемых классов с нуклеотидными последовательностями будет алфавит белков по умолчанию :(
| @@ -0,0 +1,88 @@ | |||
| class BiologicalSequence: | |||
| def __init__(self, sequence): | |||
There was a problem hiding this comment.
В целом, как говорили на паре, идеальный абстрактный класс init не содержит (чтобы нельзя было создавать его экзмепляры). Но тут конечно логично, что у каждого наследника должна быть последовательность, но лучше бы переписать это все в наследниках.
| def __repr__(self): | ||
| return f'{self.__class__.__name__}({self.sequence!r})' |
There was a problem hiding this comment.
Класс, даже repr не забыт! И все методы строки есть! Супер!
| 'S': 'Ser', 'T': 'Thr', 'W': 'Trp', 'Y': 'Tyr', 'V': 'Val'} | ||
|
|
||
| def __init__(self, sequence): | ||
| super().__init__(sequence) |
There was a problem hiding this comment.
| super().__init__(sequence) | |
| super().__init__(sequence) | |
| self.ALPHABET = {'A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y'} | |
- кажется тут смотрится логично :)
| for char in self.sequence: | ||
| if char not in self.ALPHABET: | ||
| return False | ||
| return True |
There was a problem hiding this comment.
| for char in self.sequence: | |
| if char not in self.ALPHABET: | |
| return False | |
| return True | |
| unique_chars = set(self.sequence) | |
| if not (unique_chars <= self.ALPHABET): | |
| return False | |
| return True |
There was a problem hiding this comment.
Можно избежать лишних циелов используя set :) Это не обязательно, но кажется будет работать чуть быстрее. Особенно если алфивиты тоже сразу сделаны сетами - удобная вещь!)
| def gc_content(self): | ||
| return (self.sequence.count('G') + self.sequence.count('C'))/len(self.sequence) |
There was a problem hiding this comment.
О, супер! Правда очень логично держать эту функцию тут - мы ведь ее можем и для РНК, и для ДНК использовать!
|
|
||
|
|
||
| class RNASequence(NucleicAcidSequence): | ||
| REV_TRANSCRTPTION_COMPLEMENT = {'A': 'T', 'U': 'A', 'C': 'G', 'G': 'C'} |
There was a problem hiding this comment.
алфавит тоже сюда можн перенести)
| REV_TRANSCRTPTION_COMPLEMENT = {'A': 'T', 'U': 'A', 'C': 'G', 'G': 'C'} | |
| REV_TRANSCRTPTION_COMPLEMENT = {'A': 'T', 'U': 'A', 'C': 'G', 'G': 'C'} | |
| ALPHABET = {'A','U','G','C'} |
|
|
||
| def __init__(self, sequence): | ||
| super().__init__(sequence) | ||
| self.ALPHABET = {'A','U','G','C'} |
There was a problem hiding this comment.
| self.ALPHABET = {'A','U','G','C'} |
Нет смысл держать его тут, он же относится ко всему классу. Зачем на его переобъявлять для каждого экземпляра?
| def reverse_transribe(self): | ||
| return DnaSequence(self.complement(self.REV_TRANSCRTPTION_COMPLEMENT)) |
There was a problem hiding this comment.
Супер! И дополнительная функция, и еще и может возвращать другой класс!!!
| TRANSCRTPTION_COMPLEMENT = {'A': 'U', 'T': 'A', 'C': 'G', 'G': 'C'} | ||
| def __init__(self, sequence): | ||
| super().__init__(sequence) | ||
| self.ALPHABET = {'A', 'T', 'G', 'C'} |
There was a problem hiding this comment.
| TRANSCRTPTION_COMPLEMENT = {'A': 'U', 'T': 'A', 'C': 'G', 'G': 'C'} | |
| def __init__(self, sequence): | |
| super().__init__(sequence) | |
| self.ALPHABET = {'A', 'T', 'G', 'C'} | |
| TRANSCRTPTION_COMPLEMENT = {'A': 'U', 'T': 'A', 'C': 'G', 'G': 'C'} | |
| ALPHABET = {'A', 'T', 'G', 'C'} | |
| def __init__(self, sequence): | |
| super().__init__(sequence) |
| class BiologicalSequence: | ||
| def __init__(self, sequence): | ||
| self.sequence = sequence | ||
| self.ALPHABET = {'A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y'} |
There was a problem hiding this comment.
кажется, что каждая биологическая последовательность должна иметь алфавит - это логично и верно, что прописано. Но определять его здесь не нужно, так как каждая конкертная последовательность - ДНК, РНК или белок - будет иметь свой алфавит
| @@ -0,0 +1,88 @@ | |||
| class BiologicalSequence: | |||
| def __init__(self, sequence): | |||
There was a problem hiding this comment.
не должно быть инита в абстрактном классе
| class NucleicAcidSequence(BiologicalSequence): | ||
| def complement(self, COMPLEMENT_NUCLEOTIDES=None): | ||
| if COMPLEMENT_NUCLEOTIDES is None: | ||
| COMPLEMENT_NUCLEOTIDES = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C'} |
There was a problem hiding this comment.
Наверное эта часть должна быть в ДНК и РНК отдельно, так как это позволит сразу создать их с верным алфавитом
| self.ALPHABET = {'A','U','G','C'} | ||
|
|
||
| def reverse_transribe(self): | ||
| return DnaSequence(self.complement(self.REV_TRANSCRTPTION_COMPLEMENT)) |
There was a problem hiding this comment.
верно, что возвращает объект правильного класса
| REV_TRANSCRTPTION_COMPLEMENT = {'A': 'T', 'U': 'A', 'C': 'G', 'G': 'C'} | ||
|
|
||
| def __init__(self, sequence): | ||
| super().__init__(sequence) |
There was a problem hiding this comment.
если я не ошибаюсь, получается что все super().__init__ отсылаются к биологической последовательности, но было бы лучше если бы они были в самих классах ДНК, РНК и белоков
Тут прям очень большие куски кода в тексте. Это очень здорово! Но в таком случае их точно надо оформлять штрихами (клавиша ё) чтобы было как код |
Review CNTN6