Bioinfo Blog!

blog di bioinformatica e di esperienze di studio all’estero

Guida alla programmazione a oggetti in Python

Posted by dalloliogm su settembre 12, 2007

Questa è una piccola guida per spiegare come funziona la programmazione a oggetti in python.

E’ pensata per introdurre il concetto ad un biologo o a qualcuno con poca esperienza con la programmazione, come per esempio un aspirante bioinformatico.

Essendo una guida introduttiva, vi avviso che non troverete nemmeno una linea di codice: e per ciò in linea di principio, è un tutorial accessibile anche a chi è interessato ad altri linguaggi.

Per favore, a tutti coloro più esperti di me… correggetemi se scrivo eresie!!🙂

geneobj3b.png

Intro

Allora, dovete pensare alle classi in python come a qualsiasi altro tipo di variabile: ossia, sono una struttura per immagazzinare dati, anche se più complessa di dizionari e liste.

Partiamo, come esempio, immaginando di dover rappresentare un gene con un insieme di variabili.

Per esperienza, quando si è alle prime armi con la programmazione si tende ad utilizzare un insieme piuttosto disordinato di variabili: per esempio, un dizionario per la lista di introni, uno per quella degli esoni, un’altro per i motivi regolatori, qualche dizionario nidificato per stabilire le relazioni tra le varie variabili, delle liste di tuple, etc…

Quando iniziate a vedere confusione tra le variabili che vi trovate e non sapete più distinguerle, è il momento di avvicinarsi alla programmazione ad oggetti.

Rappresentare un Gene con Python

Sappiamo che un gene può essere visto come un qualcosa a cui possiamo attribuire diverse proprietà importanti: per esempio il suo nome comune, il suo identificativo su genbank, la specie a cui appartiene, la sua sequenza di DNA, le malattie a cui è associato, le proteine che codifica, e così via.

Dimentichiamoci un attimo della programmazione in python e tracciamo un piccolo disegnino con tutto quello che ci sembra importante memorizzare quando vogliamo rappresentare un gene:

geneobj1c.png

ecco, quello sopra è un piccolo schema UML (un diagramma delle classi), che rappresenta l’oggetto Gene che vogliamo costruire.

E’ diviso in tre rettangoli (il terzo lo spiegherò fra poco), e nel secondo, sono descritti tutti gli attributi che ogni gene dovrà avere: per ognuno di essi è indicato il tipo (se è una lista, una stringa, etc..), ed il valore di default.

Potete notare da qui che una classe è qualcosa di simile ad un dizionario: potreste rappresentare lo schemino qui sopra anche con un dizionario con le voci ‘genbankId’, ‘sequenza’, etc.

Come si utilizza una classe

L’oggetto Gene scritto sopra, ammettendo di avere scritto a parte il codice che ne descrive la classe a parte, si utilizza così:

>>> from ClassiPersonalizzate import Gene
>>> a = Gene()
>>> a.nome_comune = 'Sxl'
>>> a.sequenza = 'ACATCGATCGTAGCTAGCTGATCGATCGATCGAT'
>>> print a.nome_comune
'Sxl'

(Ho mentito quando ho detto che non avrei inserito codice in questa guida!!🙂 ).

In questo esempio, noi abbiamo scritto il codice relativo alla classe in un file a parte (ClassiPersonalizzate.py), abbiamo importanto l’oggetto, e ne abbiamo creato una nuova istanza con il comando:

>>> a = Gene()

Potete notare che questa istruzione (Gene() ) non ammette parametri, e che tutti gli attributi vengono aggiunti manualmente uno alla volta (per esempio quando facciamo “a.nome_comune = ‘Sxl'”).

Sarebbe più comodo poter inizializzare automaticamente i valori di alcuni degli attributi quando si crea una nuova istanza dell’oggetto, per esempio:

>>> a = Gene('Sxl', 'gb|142141', 'Human')

E sapere che una funzione nascosta all’interno della nostra classe provvede ad associare correttamente tutti gli attributi: dicendo a python che il primo argomento di quando si lancia ‘Gene()’ è il nome_comune, il secondo é l’id su genbank, e il terzo la specie di appartenenza.

Metodi Interni: __init__

In python, questa funzione nascosta si chiama ‘__init__’, ed è anche chiamata ‘funzione costruttore’.

Aggiungiamola al diagramma UML:

geneobj2b.png

Ora io sto lasciando correre un sacco di cose… su come si scrive questa funzione, su cosa significa self, etc.
Lo faccio apposta: questo è un tutorial di introduzione alla programmazione ad oggetti in python, ma se volete diventare bravi dovete studiare altre guide, più lunghe magari.

Sta di fatto che la funzione __init__ di una classe in python è una funzione speciale che viene eseguita ogni volta che creiamo una istanza della classe stessa. La possiamo ridefinire a seconda di come ci sia più comodo: osserva il codice in fondo a questa guida per capire meglio.

Metodi di una classe

In una classe, possiamo ridefinire tanti metodi pubblici, che sono delle funzioni che possono venire eseguite sulla classe stessa.

Se conoscete un po’ di python, sapete che potete fare questo:

>>> a = 'abcd'
>>> a.upper()
ABCD
>>> a.replace('a', c')
'cbcd'

Possiamo ridefinire i metodi che più ci stanno comodi anche per una classe.

Potremmo aggiungere una funzione che ci calcoli la composizione in GC all’interno del gene.
Oppure, un’altra funzione che scarichi automaticamente la sequenza o la lista delle malattie associate al nostro gene da Internet.

Per esempio:

>>> a = Gene()
>>> a.sequenza = 'CCCCGGGGGTTTTTAAAAAA'

>>> a.CalcolaComposizioneGC()
0.50

Ecco come sarebbe il nostro diagramma delle classi:

geneobj4b.png

Ecco… queste è il significato recondito delle classi. Sono delle strutture dati, che potete ridefinire a vostro piacimento e che potete usare per modellare gli oggetti che rappresentano quello con cui avete a che fare: geni, proteine, esoni, malattie, organismi, modelli, etc.

Naturalmente vi ho già detto che non vi dovete fidare di me e che se volete conoscere le cose per bene, dovete studiare anche da altre parti🙂.

Infine, ecco il codice che rappresenterebbe la classe che vi ho descritto (wordpress permettendo):

class Gene:
    def __init__(self, nome, genbankId, specie):
        self.nome_comune = nome.capitalize()
        self.genbankId = genbankId
        self.specie = specie.capitalize()

    def CalcolaComposizioneGC(self):
        totGC = 0.0
        for base in self.sequenza:
            if base.upper() == 'C' or base.upper() == 'G':
                totGC += 1
        self.composizioneGC = totGC / len(self.sequenza)

    def ScaricaSequenzaDaGenbank(self):
        pass

    def ScaricaListaMalattieAssociate(self):
        pass

    def ScaricaListaDiGeniOrtologhiInAltriOrganismi(self):
        pass

(era una vita che non programmavo un roba del genere…🙂 con il contatore per calcolare le percentuale di GC e tutto il resto…. ma spero che questo codice sia comprensibile ai newbie… )

4 Risposte to “Guida alla programmazione a oggetti in Python”

  1. Chiamerei i metodi semplicemente metodi, perche’ “pubblici” si riferisce a metodi pubblici e privati, ma Python non implementa propriamente metodi “privati” (e forse questo aggiunge pure complessita’).

  2. dalloliogm said

    ok, cambiato.

    Il resto della guida, invece, com’è?

  3. Forse la definizione di classe come contenitore di dati e’ un po’ impropria, la classe se non ricordo male e’ che definisca/crei oggetti (perche’ non necessariamente uno usa gli attributi di una classe per metterci qualcosa, anche se e’ spesso utile), non a caso le convenzioni “di stile nuovo” (2.3+) prevedono che ogni classe erediti da “object”. In questo caso,


    class Gene:

    diventa


    class Gene(object):

    Forse due paroline sul self ci vorrebbero, basterebbe dire che i metodi self sono quelli legati alla classe stessa (bound methods).

  4. […] suo blog personale, Dalloliogm ha scritto un interessante articolo su come python può facilitare la vita dei bioinformatici . Il suo è un bel esempio di come, attraverso una serie di oggetti legati alla genetica, alle […]

Sorry, the comment form is closed at this time.

 
%d blogger cliccano Mi Piace per questo: