Skip to content

Conversation

nvaulin
Copy link
Member

@nvaulin nvaulin commented Feb 26, 2024

Review CNTN6

Copy link

@CaptnClementine CaptnClementine left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Чуть-чуть запутались в сложной теме с асбтрактным классом. Все остальное сделано очень хорошо, и получилось возвращать нужного типа при транскрипции, и освоили 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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Суть абстрактного класса - не держать в себе готовые атрибуты и методы, а только говорить какие атрибуты и/или методы должны обязательно быть у его наследников. Здесь выходит так, что у наследуемых классов с нуклеотидными последовательностями будет алфавит белков по умолчанию :(

@@ -0,0 +1,88 @@
class BiologicalSequence:
def __init__(self, sequence):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В целом, как говорили на паре, идеальный абстрактный класс init не содержит (чтобы нельзя было создавать его экзмепляры). Но тут конечно логично, что у каждого наследника должна быть последовательность, но лучше бы переписать это все в наследниках.

Comment on lines +27 to +28
def __repr__(self):
return f'{self.__class__.__name__}({self.sequence!r})'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Класс, даже repr не забыт! И все методы строки есть! Супер!

'S': 'Ser', 'T': 'Thr', 'W': 'Trp', 'Y': 'Tyr', 'V': 'Val'}

def __init__(self, sequence):
super().__init__(sequence)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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'}
  • кажется тут смотрится логично :)

Comment on lines +31 to +34
for char in self.sequence:
if char not in self.ALPHABET:
return False
return True

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно избежать лишних циелов используя set :) Это не обязательно, но кажется будет работать чуть быстрее. Особенно если алфивиты тоже сразу сделаны сетами - удобная вещь!)

Comment on lines +47 to +48
def gc_content(self):
return (self.sequence.count('G') + self.sequence.count('C'))/len(self.sequence)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

О, супер! Правда очень логично держать эту функцию тут - мы ведь ее можем и для РНК, и для ДНК использовать!



class RNASequence(NucleicAcidSequence):
REV_TRANSCRTPTION_COMPLEMENT = {'A': 'T', 'U': 'A', 'C': 'G', 'G': 'C'}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

о! Класс!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

алфавит тоже сюда можн перенести)

Suggested change
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'}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self.ALPHABET = {'A','U','G','C'}

Нет смысл держать его тут, он же относится ко всему классу. Зачем на его переобъявлять для каждого экземпляра?

Comment on lines +58 to +59
def reverse_transribe(self):
return DnaSequence(self.complement(self.REV_TRANSCRTPTION_COMPLEMENT))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Супер! И дополнительная функция, и еще и может возвращать другой класс!!!

Comment on lines +63 to +66
TRANSCRTPTION_COMPLEMENT = {'A': 'U', 'T': 'A', 'C': 'G', 'G': 'C'}
def __init__(self, sequence):
super().__init__(sequence)
self.ALPHABET = {'A', 'T', 'G', 'C'}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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'}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

кажется, что каждая биологическая последовательность должна иметь алфавит - это логично и верно, что прописано. Но определять его здесь не нужно, так как каждая конкертная последовательность - ДНК, РНК или белок - будет иметь свой алфавит

@@ -0,0 +1,88 @@
class BiologicalSequence:
def __init__(self, sequence):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не должно быть инита в абстрактном классе

class NucleicAcidSequence(BiologicalSequence):
def complement(self, COMPLEMENT_NUCLEOTIDES=None):
if COMPLEMENT_NUCLEOTIDES is None:
COMPLEMENT_NUCLEOTIDES = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C'}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Наверное эта часть должна быть в ДНК и РНК отдельно, так как это позволит сразу создать их с верным алфавитом

self.ALPHABET = {'A','U','G','C'}

def reverse_transribe(self):
return DnaSequence(self.complement(self.REV_TRANSCRTPTION_COMPLEMENT))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

верно, что возвращает объект правильного класса

REV_TRANSCRTPTION_COMPLEMENT = {'A': 'T', 'U': 'A', 'C': 'G', 'G': 'C'}

def __init__(self, sequence):
super().__init__(sequence)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

если я не ошибаюсь, получается что все super().__init__ отсылаются к биологической последовательности, но было бы лучше если бы они были в самих классах ДНК, РНК и белоков

@nvaulin
Copy link
Member Author

nvaulin commented Mar 17, 2024

Чуть-чуть запутались в сложной теме с асбтрактным классом. Все остальное сделано очень хорошо, и получилось возвращать нужного типа при транскрипции, и освоили 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)

Так получится хранить каждый нужный алфавит в своем классе.

Хорошая работа!

Тут прям очень большие куски кода в тексте. Это очень здорово! Но в таком случае их точно надо оформлять штрихами (клавиша ё) чтобы было как код

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants