Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre à l'essai
    POO: fonction de retour, liste et AttributeError
    Bonjour à tous,

    Je poursuis mon apprentissage de la programmation en python. J'ai abordé la POO. Je suis en train d'écrire un programme dont le but est d'ouvrir et analyser un fichier fasta avec diverses méthodes.

    Voici mon code:

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
     
    import os, sys
     
    pyScriptName = sys.argv[0]
    RNASequence = sys.argv[1]
    #outputProtein = sys.argv[2]                                                                                                             
     
    # Dictionnaire codon                                                                                                                        
     
    Codon = {
        "AUG": "Methionine",
        "UUU": "Phenylalanine",
        "UUC": "Phynylalanine",
        "UUA": "Leucine",
        "UUG": "Leucine",
        "UCU": "Serine",
        "UCC": "Serine",
        "UCA": "Serine",
        "UCG": "Serine",
        "UAU": "Tyrosine",
        "UAC": "Tyrosine",
        "UGU": "Cysteine",
        "UGC": "Cysteine",
        "UGG": "Tryptophan",
        "UAA": "STOP",
        "UAG": "STOP",
        "UGA": "STOP"
    }
     
    fasta_dict = {}
     
    class Fasta():
        """Classe pour manipuler des fichiers fasta."""
        def __init__(self, RNASequence):
            self.RNASequence = RNASequence
     
        def openFasta(self):
    	"""ouvre un fichier fasta, stocke l'id et la séquence dans un dictionnaire."""
            with open(RNASequence, "r") as fasta_file:
                sequence_id = ""
                for line in fasta_file:
                    if line.startswith(">"):
                        sequence_id = line.strip()
                        fasta_dict[sequence_id] = ""
                    else:
                        fasta_dict[sequence_id] += line.strip()
                return(fasta_dict)
     
        def sequence(self):
    	"""Récuperer la sequence"""
    	seq_list = []
    	for seque in fasta_dict:
                seq_list.append(fasta_dict[seque])
    	return(seq_list)
     
        def RNAtoProteins(self):
    	"""Traduire la sequence ARN en protéine."""
            for sequen in seq_list:
                print(sequen)
                protein = []
                for i in range(0, len(sequen), 3):
                    aa = Codon[sequen[i:i+3]]
                    protein.append(aa)
                    if aa == "STOP":
                        break
                return(protein)
     
    if __name__ == "__main__":
        test_file = Fasta(RNASequence)
        my_file = test_file.openFasta()
        print("Voici le resultat")
        print(my_file)
        result2 = test_file.sequence()
        print("Resultat de .sequence")
        print(result2)
        proteinefromRNA = result2.RNAtoProteins()
        print(proteinefromRNA)


    Lorsque, j'exécute le code avec les séquences dans un fichier fasta (voir ci-dessous), j'obtiens le message d'erreur suivant:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    AttributeError: 'list' object has no attribute 'RNAtoProteins'


    Si j'ai bien compris, cette erreur me dit que l'assignation de l'attribut ne fonctionne pas. Que faire pour corriger cela ?

    Merci pour votre aide.

    A bientôt !

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    >Sequence 1
    AUGUUUUCUUAAAUG
     
    >Sequence 2
    AUGUUUUCUAAAAUGCUUAUAGCAGCUAAU
     
    >Sequence 3
    AUGUUUUCUUAAAUUAUGCCCGUAA

  2. #2
    Rédacteur



    Après plusieurs corrections , j'arrive à quelque chose qui tournera peut être !

    Je ne sais pas tester puisque je n'ai pas le fichier fa.

    Code Python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    class Fasta():
        """Classe pour manipuler des fichiers fasta."""
     
        def __init__(self, RNASequence):
            self.RNASequence = RNASequence
     
        def openFasta(self):
            """ouvre un fichier fasta, stocke l'id et la séquence dans un dictionnaire."""
            with open(self.RNASequence, "r") as fasta_file:
                sequence_id = ""
                for line in fasta_file:
                    if line.startswith(">"):
                        sequence_id = line.strip()
                        fasta_dict[sequence_id] = ""
                    else:
                        fasta_dict[sequence_id] += line.strip()
     
        def sequence(self):
            """Récuperer la sequence"""
            seq_list = []
            for seque in fasta_dict:
                seq_list.append(fasta_dict[seque])
            return seq_list
     
        def RNAtoProteins(self, seq_list):
            """Traduire la sequence ARN en protéine."""
            protein = []
            for sequen in seq_list:
                for i in range(0, len(sequen), 3):
                    aa = Codon.get(sequen[i:i+3], '')
                    protein.append(aa)
                    if aa == "STOP":
                        break
            return protein
     
     
    if __name__ == "__main__":
        f = Fasta(RNASequence)
        f.openFasta()
        print(fasta_dict)
        seqs = f.sequence()
        print(seqs)
        proteinefromRNA = f.RNAtoProteins(seqs)
        print(proteinefromRNA)

  3. #3
    Expert éminent sénior
    Bonjour
    Citation Envoyé par benoit3166 Voir le message
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        def sequence(self):
    	"""Récuperer la sequence"""
    	seq_list = []
    	for seque in fasta_dict:
                seq_list.append(fasta_dict[seque])
    	return(seq_list)
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
        def sequence(self):
    	"""Récuperer la sequence"""
    	return fasta_dict.values()				# Eventuellement yield from fasta_dict.values()


    Ca ne résoudra pas ton problème puisque tu ne donnes ni la ligne où il se produit, ni un jeu d'essai pour pouvoir le reproduire ; mais ça simplifiera au-moins ton code. Et en plus, comme une "values()" d'un dictionnaire reste associée au dictionnaire, si le dico évolue après coup, la vue évolue avec (ce que ne fait pas une liste figée)
    PS: je ne pige pas pourquoi "fasta_dict" est une globale alors qu'elle pourrait être intégrée dans l'objet "fasta".
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  4. #4
    Expert éminent sénior
    Salut,

    Citation Envoyé par benoit3166 Voir le message
    Si j'ai bien compris, cette erreur me dit que l'assignation de l'attribut ne fonctionne pas. Que faire pour corriger cela ?
    result2 est la liste retournée par la méthode .sequence.
    Une liste n'est pas un Fasta et n'a aucune raison d'avoir RNAtoProteins comme attribut.

    Un objet (créer ou non avec "class"), c'est définir un état (sous la forme d'attributs) et des méthodes (qui modifient éventuellement l'état).
    note: dans le code, "l'état" va être reflété par des variables d'instances sous la forme self.variable.

    Il n'est pas interdit de fabriquer une classe qui soit juste une collection de fonctions (dans une boîte on met un peu ce qu'on veut), mais çà reste des fonctions: une opération qui récupérè des objets en entrée et en produit d'autres (ou les transforme) en sortie....

    Entre d'un côté des fonctions sans état et de l'autre des "class" qui permettent d'avoir un état, on est entre deux modèles assez différents qu'on évite de mélanger.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Rédacteur

    Citation Envoyé par Sve@r Voir le message
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
        def sequence(self):
    	"""Récuperer la sequence"""
    	return fasta_dict.values()
    Pour obtenir le même résultat que le code original, une list, il faut écrire :

    Code Python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
        def sequence(self):
            """Récuperer la sequence"""
            return list(fasta_dict.values())

  6. #6
    Expert éminent sénior
    Citation Envoyé par danielhagnoul Voir le message
    Pour obtenir le même résultat que le code original, une list, il faut écrire :

    Code Python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
        def sequence(self):
            """Récuperer la sequence"""
            return list(fasta_dict.values())
    Ouaip. Comme je l'ai dit, le souci c'est que tu obtiens un truc indexable ok, mais un truc figé. Si le dico évolue après, ben tant pis.
    Perso je préfère obtenir une vue. Et si je dois l'indexer alors j'indexe ma vue "à la volée". Exemple tab=Fasta(truc).sequence(); print(tuple(tab)[0]). Toutefois je n'ai jamais eu l'utilité d'indexer les keys/values/items d'un dico (itérer dessus oui, mais taper via un index...?)

    Mais je suis d'accord avec toi, ma version ne reproduit plus le code d'origine avec exactitude
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  7. #7
    Membre à l'essai
    Bonjour à tous,

    Merci pour vos réponses fort intéressantes.

    J'aurai du préciser le but de mon programme. Il s'agit d'un programme qui lit un fichier fasta, récupère la ou les différente(s) séquence(s) d'ARN et à partir de celle(s)-ci, donne la séquence protéique. A terme, mon but est de faire un petit GUI avec Tkinter, lorsque j'aurai abordé cette partie. Pour l'instant, je souhaite maîtriser la POO et visiblement, il faut que je revois les notions.

    Ca ne résoudra pas ton problème puisque tu ne donnes ni la ligne où il se produit, ni un jeu d'essai pour pouvoir le reproduire
    @Sve@r, j'ai bien donné un jeu d'essai dans mon premier post (tout en bas du post et j'aurai du être plus explicite). De plus, je pensais que le lien (dans la première ligne) vers fichier fasta serait suffisant. Je me suis trompé.

    Je remet ci-dessous l'exemple de fichier test. Il suffit de le copier-coller dans un éditeur et d'enregistrer le fichier avec l'extension .fasta.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    >Sequence 1
    AUGUUUUCUUAAAUG
     
    >Sequence 2
    AUGUUUUCUAAAAUGCUUAUAGCAGCUAAU
     
    >Sequence 3
    AUGUUUUCUUAAAUUAUGCCCGUAA


    Quant au message d'erreur, il se produit à la ligne 76 de mon code.

    En relisant le message de Daniel et Sve@r, à propos de la liste et du dictionnaire. Je pense que c'est effectivement une mauvaise idée d'utiliser une liste. Je perds l'information du nom des séquences protéique, qui ne change pas. Il faudrait donc à partir de fasta_dict, créer un nouveau dictionnaire qui garderai le nom des séquences comme clé et contiendrais comme valeur la séquence protéique transcrite à partir de la séquence d'ARN. Je vais réfléchir à comment faire ça.

    D'après le message de wiztricks, j'ai compris qu'il serait plus simple de faire juste des fonctions, plutôt qu'une classe avec plein de méthodes, qui sont en fait que des fonctions. C'est bien ça ?

    C'est fort instructif et il me reste encore beaucoup de travail pour maîtriser toutes ces notions et les appliquer. Plus je code, plus j'apprécie de coder.

  8. #8
    Expert éminent sénior
    Citation Envoyé par benoit3166 Voir le message
    Pour l'instant, je souhaite maîtriser la POO et visiblement, il faut que je revois les notions.
    Bah, c'est pas mal comme début. Des maladresses oui mais rien de vraiment mauvais.

    Citation Envoyé par benoit3166 Voir le message
    @Sve@r, j'ai bien donné un jeu d'essai dans mon premier post (tout en bas du post et j'aurai du être plus explicite). De plus, je pensais que le lien (dans la première ligne) vers fichier fasta serait suffisant. Je me suis trompé.
    Ben c'est plus facile d'avoir un jeu d'essai que d'aller chercher dans wikipedia le détail du format, l'étudier et ensuite se construire péniblement son propre jeu d'essai pour tenter de reproduire ton problème. Mais j'avais pas compris que ton exemple en bas du premier post était un vrai fichier. Je pensais que c'était une sortie écran.

    Citation Envoyé par benoit3166 Voir le message
    En relisant le message de Daniel et Sve@r, à propos de la liste et du dictionnaire. Je pense que c'est effectivement une mauvaise idée d'utiliser une liste. Je perds l'information du nom des séquences protéique, qui ne change pas. Il faudrait donc à partir de fasta_dict, créer un nouveau dictionnaire qui garderai le nom des séquences comme clé et contiendrais comme valeur la séquence protéique transcrite à partir de la séquence d'ARN. Je vais réfléchir à comment faire ça.
    Donc si dico1 est un dictionnaire qui a des clefs et des valeurs, et que dico2 doit être un dictionnaire qui a les mêmes clefs et d'autres valeurs calculées à partir de celles du premier, t'as grosso-modo 2 solutions
    S1: tu crées dico2 à partir de dico1
    Code python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    for (k, v) in dico1.items():
    	dico2[k]=expression utilisant v

    Qu'on peut écrire avec une liste en intension: dico2=dict((k, expression_utilisant v) for (k, v) in dico1.items()).

    S2: Tu crées un seul dico contenant des sous-dico comme valeur
    Code python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    dico={
    	"seq1" : {
    		"data" : la_data_de_base 1,
    		"res" : None,
    	},
    	"seq2" : {
    		"data" : la_data_de_base 2,
    		"res" : None,
    	},
    	"seq3" : {
    		"data" : la_data_de_base 3,
    		"res" : None,
    	},
    	...
    }


    Ensuite t'as plus qu'à balayer le dico et calculer chaque "res" en fonction de sa "data"
    Code python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    for v in dico.items():
    	v["res"]=expression_utilisant v["data"]


    Citation Envoyé par benoit3166 Voir le message
    D'après le message de wiztricks, j'ai compris qu'il serait plus simple de faire juste des fonctions, plutôt qu'une classe avec plein de méthodes, qui sont en fait que des fonctions. C'est bien ça ?
    C'est vrai qu'une classe sans attribut ne se justifie pas vraiment (on enlève la classe, on garde juste les méthodes qui deviennent de simples fonctions) mais je pense que ta classe pourrait plus tard, si ton code évolue et s'enrichit de certains détails, avoir alors des attributs qui donc justifieront son existence. Peut-être que le dico de tes séquences génétiques pourra devenir attribut au lieu de le laisser en globale
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  9. #9
    Expert éminent sénior
    Salut,

    Citation Envoyé par benoit3166 Voir le message
    D'après le message de wiztricks, j'ai compris qu'il serait plus simple de faire juste des fonctions, plutôt qu'une classe avec plein de méthodes, qui sont en fait que des fonctions. C'est bien ça ?
    Vous constatez que vous effectuez une suite de transformations: fichier -> dictionnaire -> liste -> ...
    Qu'est ce qui "persiste"/doit être transmis d'une transformation à l'autre?
    Répondre à cette question pourrait aider à définir des "attributs" i.e. des objets qu'il serait souhaitable/utile de voir perdurer au delà de la durée de vie d'une simple fonction.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Membre à l'essai
    Salut,

    Merci pour vos retours.


    Vous constatez que vous effectuez une suite de transformations: fichier -> dictionnaire -> liste -> ...
    Qu'est ce qui "persiste"/doit être transmis d'une transformation à l'autre?
    Répondre à cette question pourrait aider à définir des "attributs" i.e. des objets qu'il serait souhaitable/utile de voir perdurer au delà de la durée de vie d'une simple fonction.
    Un fichier fasta peut contenir une ou plusieurs séquences. Le but est de transformer les séquences d'ARN du fichier fasta en séquences protéiques. Ce qui doit persiter/rester au cours des transformation, c'est le nom des séquences. Elles sont stockés comme des clés dans le dictionnaire fasta_dict. Le dictionnaire fasta_dict doit être propre à chaque fichier fasta. Ce qui doit être transmis d'une transformation à l'autre, c'est la valeur de fasta_dict, afin de produire la séquence protéique. Dans mon code initial, je l'ai fait via la liste pour la transformer. Mais comme me l'ont fait remarqué Sve@r et Daniel, avec ce code, je perd le nom des séquences.

    Après réflexion, j'ai commencé à modifier mon script de la façon suivante.

    • J'ai décidé de faire 2 classes dont l'une sera hérité.
    • fasta_dict sera un attribut de la classe mère Fasta. Deux méthodes pourront agir sur les attributs de cette classe: open_fasta (ouvre un fichier fasta) et write_fasta (ecrit un fichier fasta). Cette dernière est utile pour enregistrer la nouvelle séquence protéique.
    • La classe fille sera la classe RNAtoProtein, elle va transformer les valeurs contenus dans fasta_dict en séquence ARN à l'aide d'une méthode (translate_to_proteins) et du dictionnaire Codon.
    • Je réfléchis au niveau des attributs de la classe fille RNAtoProtein.
    • Je n'exclue pas, plus tard, de faire une autre classe fille pour transformer, par exemple, les séquences d'ADN en ARN (avec par exemple: Class ADNtoARN()).


    Dans le code ci-dessous, j'ai placé le dictionnaire fasta_dict dans le constructeur de la classe Fasta. Est-ce une bonne chose ?

    Voici ci-dessous le début de mon script modifié et non-testé:

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
     
    """                                                                                                                                                                                                                                                                             
       Protein_translation input_DNA_file.fasta output_protein_file.fasta                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                    
       argument 1: name of the DNA fasta file to translate into protein sequence                                                                                                                                                                                                    
       argument 2: name of the RNA sequence file (in fasta)                                                                                                                                                                                                                         
       argument 3: name of the protein sequence file (in fasta)                                                                                                                                                                                                                     
    """
     
    import os, sys
     
    pyScriptName = sys.argv[0]
    fasta = sys.argv[1]
    #outputProtein = sys.argv[2]  # pour enregistrer la sequence protéique au format fasta, la méthode writeFasta sera écrite plus tard
     
    # Dictionnaire codon (ne change jamais)                                                                                                                                                                                                                                                    
     
    Codon = {
        "AUG": "Methionine",
        "UUU": "Phenylalanine",
        "UUC": "Phynylalanine",
        "UUA": "Leucine",
        "UUG": "Leucine",
        "UCU": "Serine",
        "UCC": "Serine",
        "UCA": "Serine",
        "UCG": "Serine",
        "UAU": "Tyrosine",
        "UAC": "Tyrosine",
        "UGU": "Cysteine",
        "UGC": "Cysteine",
        "UGG": "Tryptophan",
        "UAA": "STOP",
        "UAG": "STOP",
        "UGA": "STOP"
    }
     
    class Fasta():
        """ Classe principale pour lire et ecrire un fichier fasta."""
        def __init__(self, fasta, fasta_dict = {}):
            self.fasta = fasta
            self.fasta_dict = fasta_dict
     
        def open_fasta(self):
            """Ouvre un fichier fasta, enregistre les noms des sequences et les sequences dans un dictionnaire."""
            with open(fasta, "r") as fasta_file:
                sequence_id = ""
                for line in fasta_file:
                    if line.startswith(">"):
                        sequence_id = line.strip()
                        self.fasta_dict[sequence_id] = ""
                    else:
                        self.fasta_dict[sequence_id] += line.strip()
                return(self.fasta_dict)
     
        def write_fasta(self):
            """Ecris un fichier fasta avec une sequence proteique"
            pass
     
    class RNAtoProtein(Fasta):
        """Traduire un ARN en une proteine"""
        def __init__(self):
            pass
     
        def rna_sequence(self):
            """Recupérer la sequences ARN."""
            pass
     
        def translate_to_proteins(self):
            """Traduire la sequence ARN en une proteine et l'enregistrer dans un nouveau dictionnaire avec l'id de fasta_dict."""
            pass
     
    if __name__ == "__main__":
       test_file = Fasta(fasta)
       print(test_file)
       ouvert = test_file.open_fasta()
       print(ouvert)


    Qu'en pensez-vous ?

  11. #11
    Expert éminent sénior
    Citation Envoyé par benoit3166 Voir le message
    La classe fille sera la classe RNAtoProtein, elle va transformer les valeurs contenus dans fasta_dict en séquence ARN à l'aide d'une méthode (translate_to_proteins) et du dictionnaire Codon.
    Je réfléchis au niveau des attributs de la classe fille RNAtoProtein.
    Ce n'est pas interdit, mais je ne pense pas que ce soit nécessaire. Un héritage ne se justifie déjà que si tu as plusieurs objets, et que ces objets ont un ancètre commun. En POO on a d'ailleurs l'habitude de dire que l'héritage se représente par un "c'est un". Exemple un avion est un véhicule, une voiture est un véhicule. Si j'ai juste une voiture alors j'ai juste un objet "voiture". Déjà même si tu réfléchis aux attributs de la classe fille, c'est que tu n'en as pas vraiment besoin.

    Citation Envoyé par benoit3166 Voir le message
    Je n'exclus pas, plus tard, de faire une autre classe fille pour transformer, par exemple, les séquences d'ADN en ARN (avec par exemple: Class ADNtoARN()).
    Hé oui, tu utilises l'objet pour des actions. Or un objet c'est une chose, pas une action. Bien entendu la chose elle peut faire des actions.

    En fait, tu pars du fasta comme si c'était là le principal élément que tu manipules, alors que le fasta n'est qu'un support de stockage de l'information. Pour moi, l'information que tu manipules (donc ton objet) c'est la chaine ARN. Cette chaine pourra éventuellement se faire "charger" depuis un fasta (méthode "loadFromFasta()"), être "transformée en séquence protéique" (méthode "toARN()"), être affichée comme on affiche une string (méthode "__str__()"), etc.

    Citation Envoyé par benoit3166 Voir le message
    Dans le code ci-dessous, j'ai placé le dictionnaire fasta_dict dans le constructeur de la classe Fasta. Est-ce une bonne chose ?
    C'est excellent (enfin en faisant abstraction que je considère que tu es mal parti avec l'objet Fasta). Puisqu'il fait partie de l'objet au naturel, il doit en faire partie informatiquement.

    Toutefois petit bémol: il est très dangereux d'utiliser un "mutable" (liste, dico) comme valeur par défaut d'un paramètre. Parce que la valeur par défaut est créée quand la fonction est créée, pas quand elle est appelée.
    Ce qui signifie que si le mutable est modifié dans la fonction, alors il est modifié pour tout le monde y compris les appels futurs.
    Exemple
    Code python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> def f(n, tab=[]):
    ...	tab.append(n)
    ...	return tab
    ...
    >>> f(1)
    [1]
    >>> f(2)
    [1, 2]
    >>> f(3)
    [1, 2, 3]

    A chaque appel de f sans second paramètre, on aurait pu penser qu'il prendrait un tableau vide pour démarrer. Or on voit bien qu'il reprend le tableau créé lors de l'appel précédent.

    Pour reproduire le vrai comportement du tableau vide par défaut, faut utiliser une valeur non mutable comme défaut (ie None) et ensuite tester cette valeur
    Code python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> def f(n, tab=None):
    ...	if tab is None: tab=[]
    ...	tab.append(n)
    ...	return tab
    ...
    >>> f(1)
    [1]
    >>> f(2)
    [2]
    >>> f(3)
    [3]


    Donc pour ton __init__, ce serait
    Code python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Fasta():
        """ Classe principale pour lire et ecrire un fichier fasta."""
        def __init__(self, fasta, fasta_dict = None):
            self.fasta = fasta
            self.fasta_dict = fasta_dict if fasta_dict is not None else {}
        ...
    # class Fasta()


    Ensuite tu pourrais placer Codon comme attribut statique de ton objet puisque lui il est associé à la notion d'objet Fasta et non à une instance d'objet Fasta.
    Code python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    class Fasta():
        """ Classe principale pour lire et ecrire un fichier fasta."""
        Codon = {
            "AUG": "Methionine",
            "UUU": "Phenylalanine",
            "UUC": "Phynylalanine",
            "UUA": "Leucine",
            "UUG": "Leucine",
            "UCU": "Serine",
            "UCC": "Serine",
            "UCA": "Serine",
            "UCG": "Serine",
            "UAU": "Tyrosine",
            "UAC": "Tyrosine",
            "UGU": "Cysteine",
            "UGC": "Cysteine",
            "UGG": "Tryptophan",
            "UAA": "STOP",
            "UAG": "STOP",
            "UGA": "STOP"
        }
        def __init__(self, fasta, fasta_dict = None):
            self.fasta = fasta
            self.fasta_dict = fasta_dict if fasta_dict is not None else {}
        ...
    # class Fasta()


    De là ça ne change presque rien. Simplement chaque fois que tu veux utiliser Codon, tu peux le nommer Fasta.Codon si c'est depuis l'extérieur ou l'intérieur de l'objet ; avec possibilité en plus de le nommer self.Codon si c'est depuis l'intérieur de l'objet (perso j'aime pas trop, j'aime bein voir quand je manipule un attribut statique).
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  12. #12
    Expert éminent sénior
    Salut,

    Citation Envoyé par benoit3166 Voir le message
    Dans le code ci-dessous, j'ai placé le dictionnaire fasta_dict dans le constructeur de la classe Fasta. Est-ce une bonne chose ?
    Tant que le code fonctionne et fait le boulot qu'on en attend, ranger des instructions dans des fonctions ou dans une ou plusieurs classes, ne change pas grand chose côté "fonctionnel" (çà fait le même boulot).

    Si çà change des choses, ce sera sur des aspects non fonctionnels: écrire le code en le testant pas à pas, réutiliser certaines fonctionnalités, faciliter l'ajout de fonctionnalités,...

    Ces aspects, critères qui motivent le choix d'une organisation par rapport à d'autres, sont définies en fonction du "projet": coder un exemple ne demande pas les mêmes exigences que coder le système de contrôle d'un peace maker.

    Et réciproquement, vous n'allez pas vous embêter à coder avec des contraintes qui ne font pas trop de sens si ce n'est pas nécessaire.... Sauf pour vous exercer, mais là vous avez des tutos. qui proposent explications, exercices et corrections.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels