IntEnum so in der Verwendung sinnvoll?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Inatrox
User
Beiträge: 6
Registriert: Montag 26. Juni 2023, 12:44

Hallo Leute,

da ich noch nicht so lange mit Python programmiere, bin ich mit den allgemeinen Konzepten der Sprache noch nicht so vertraut. Dazu habe ich mir ein Buch über Algorithmen in Python gekauft, in dem IntEnum verwendet werden. Doch irgenwie kommt mir die Verwendung der IntEnum so relativ komisch vor, zudem meckert mein Compiler da etwas. Dazu also die Frage, ob man IntEnum so überhaupt verwendet? Dazu ist zu erwähnen, dass nur das Prinzip der linearen Suche erklärt werden sollte (__contains__() wurde darunter erklärt).

Code: Alles auswählen

from enum import IntEnum
from typing import Tuple, List

Nucleotide: IntEnum = IntEnum('Nucleotide', ('A', 'C', 'G', 'T'))
Codon = Tuple[Nucleotide, Nucleotide, Nucleotide]  #Type-Alias für Codons
Gene = List[Codon]  #Typ-Alias für Gene

gene_str = "ACGTATTGCTAGCTAGGCTAGCT"

def string_to_gene(s) -> Gene:
    gene = []
    for i in range(0, len(s), 3):
        if (i + 2) >= len(s):   #Nicht über das Ende hinausschießen!
            return gene
        #Codon aus drei Nukleotiden initsialisiert
        codon = (Nucleotide[s[i]], Nucleotide[s[i + 1]], Nucleotide[s[i +2]])
        gene.append(codon)
    return gene


def linear_contains(gene: Gene, key_codon: Codon) -> bool:
    for codon in gene:
        if codon == key_codon:
            return True
    return False


if __name__ == "__main__":
    my_gene = string_to_gene(gene_str)
    acg = (Nucleotide.A, Nucleotide.C, Nucleotide.G)
    print(linear_contains(my_gene, acg))
LG Inatrox
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Inatrox: Was meckert der Compiler denn? Sicher das es der Compiler ist und nicht was auch immer Du zur Prüfung von Typannotationen verwendest?

Ich sehe hier keinen Grund für `IntEnum`. Das könnte man genau so gut als Enum machen. `IntEnum` ist für Fälle wo man tatsächlich die Eigenschaft benötigt, dass die Enum-Werte auch gleichzeitig Zahlen sind. Das ist oft bei APIs der Fall wo eigentlich Zahlen verwendet werden, man aber lieber etwas lesbareres als irgendwelche magischen Zahlen hat.

Im Namen `gene_str` sollte der Grunddatentyp `str` nicht vorkommen und da es sich um eine Konstante handelt, wird das KOMPLETT_GROSS geschrieben.

Der Präfix `my_` ist sinnlos sofern es nicht noch ein `our_gene` oder `their_gene` oder so gibt, gegen den sich ”mein” Gen abgrenzen muss.

`s` ist wie die meisten einbuchstabigen Namen kein guter Name. Indexvariablen wie `i` und `j`, oder `x`, `y`, und `z` für Koordinaten, aber das meiste andere sollte einen sinnvollen beschreibenden Namen bekommen.

`string_to_gene()` ist ein bisschen umständlich geschrieben. Statt die Umwandlung von einem Buchstaben in ein `Nucleotide` drei mal hinzuschreiben, könnte man das *einmal* hinschreiben in einem Ausdruck der alle Buchstaben umwandelt. Und danach zerteilt man das dann in 3er-Tupel. Und auch ohne gesondertes ``if``, denn man kann diesen Fall ja bereits beim erzeugen des passenden `range()`-Objekts berücksichtigen.

Bei `linear_contains()` wird der ``in``-Operator nachprogrammiert. Das macht nicht wirklich Sinn.

Code: Alles auswählen

#!/usr/bin/env python3
from enum import Enum

Nucleotide = Enum("Nucleotide", ("A", "C", "G", "T"))

GENE_TEXT = "ACGTATTGCTAGCTAGGCTAGCT"


def string_to_gene(text):
    nucleotides = [Nucleotide[character] for character in text]
    return [
        tuple(nucleotides[i : i + 3]) for i in range(0, len(text) // 3 * 3, 3)
    ]


def main():
    gene = string_to_gene(GENE_TEXT)
    print((Nucleotide.A, Nucleotide.C, Nucleotide.G) in gene)


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Inatrox
User
Beiträge: 6
Registriert: Montag 26. Juni 2023, 12:44

@__blackjack__ danke für die hilfreiche Antwort. Die Punkte werde ich noch anpassen.

Bei dem Codeausschnitt :

Code: Alles auswählen

Nucleotide: IntEnum = IntEnum('Nucleotide', ('A', 'C', 'G', 'T'))
Kam folgende Meldung: Expected type 'IntEnum', got 'Type[Enum]' instead

Bei dem Codeauschnitt:

Code: Alles auswählen

codon = (Nucleotide[s[i]], Nucleotide[s[i + 1]], Nucleotide[s[i +2]])
Kam folgende Meldung: Class 'IntEnum' does not define '__getitem__', so the '[]' operator cannot be used on its instances
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Inatrox: Was verwendest Du denn zum Prüfen von Typannotationen und in welcher Version? Mypy hat damit keine Probleme.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Inatrox
User
Beiträge: 6
Registriert: Montag 26. Juni 2023, 12:44

@__blackjack__ Ich benutze PyCharm mit der Version 2023.1.4. Der Python Interpreter hat die Version 3.10.
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Benutzt PyCharm da was eigenes um die Typprüfung durchzuführen? Hab's gerade mit Python 3.10 und mypy geprüft, das meckert nur das `gene` in Zeile 11 nicht annotiert ist und hat keine Probleme mit den vorhandenen Annotationen. Also korrekterweise nicht, denn die Meldungen von PyCharm sind ja falsch.

Bei Python 3.10 braucht man auch `Tuple` und `List` nicht mehr aus `typing` sondern kann die eingebauten Datentypen direkt verwenden, also `tuple` und `list`. Bei älteren Python-Versionen geht das auch schon, wenn man ``from __future__ import annotations`` macht. Aber ich bin kein grosser Fan von Typannotationen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Inatrox
User
Beiträge: 6
Registriert: Montag 26. Juni 2023, 12:44

@__blackjack__ Das finde ich ja spannend. Was PyCharm da genau benutzt weiß ich auch nicht genau, die Installation von Mypy ist aber scheinbar optional und nicht standartmäßig vorgegeben. Ich werde genau wegen solcher Probleme auch nicht so ganz warm mit PyCharm. Vielleicht sollte ich da doch mal die IDE wechseln.
Antworten