Sei sulla pagina 1di 6
Licenza: 5¢(yhan Scare Foundation) Tipo: Progfarmaione Sito Web: w.pythen.ocg Download esempi: hp/anc.atekcr ython ® un linguaggio ad alto livello a tipizzazione dinami ‘ea © orientato agli oggetti, caratteristion questa che abbia- mo implicitamente affrontato nei precedenti appuntament osservando che qualunque cosa andassimo a creare (una variabile, tuna stringa o anche una costante!) fosse considerata da Python come un oggetto. E se volessimo creare noi un nostro tipo, un nuovo oggetto, come dovremmo procedere? La domanda @ tecita ppoiché negli esempi fin qui analizzati abbiamo fatto uso esclu sivamente della programmazione struturata e procedurale molto simile, ¢tipica, del linguaggio C. I! motivo di questo mode di pro- cedere @ intuibile: come vedremo, i “nuovi oggetti” che yogtiamo (0 vorremmo) creare saranno caratterizzati da segmenti di codice (sequenze di istruzioni) di programmazione strutturata ASTRARRE | DATI AA partite da questo paragrafo cambieremo il paradigma di ragio- namento passando alla progettazione orientata agli oggetti (OOD - Object Oriented Design) ¢ quindi alle programmazione orien- tata agli oggetti (OOP - Object Oriented Programming) i cui capostipiti sono stati linguaggi Smalltalk e Simula 67. Iniziamo ‘con il guardarci attorno: cosa vediamo? Ovunque focalizziamo la nostra attenzione vedremo un qualche oggetto, come libri efo ri viste, una pianta, automobili in strada, i] computer, eve. La OOP astrae { dati in contenitori noti con il nome di classi le quali capsulano le propri attributi) ¢ le funzioni, ovvero me todi e operazioni, permessi su di ess, I termine incapsulamento non @ utilizzato a caso ma legato al concetto di racchiudere in un ore siamo ai collaborator’ in una azienda. In Fig. | possiamo osservare 1 attribute metodi ad esso riconducibili. Ad esempio, pen- PYTHON E LA PROGRAMMAZIONE A OGGETTI Prima di addentrarei in programmi un po' pit) complessi gettiamo le fondamenta di Python. In questo appuntamento vedremo come creare l'oggetto classe Michele Petrecea tuna possibile rappresemtazione di uns classe Collaboratori le cai informazioni utili (li attibuti) potranno essere proprietd come ‘Nome, Cognome, Indirizzo, ecc. Le azioni (i metodi) che operano sulle informazioni potranno essere Assumi, Licencia e Paga. In sostanza I oggetto Collaborator’ incupsulerd tutte queste informa- zioni al suo interno. Tutto i personale di una azienda potrebbe essere quindi rappre- sentato dalla classe Collaboratori per i quali Sono tutti identificati e identficabili con elementi comuni come I'inserimento nel da- tabase di nuovi collaboratori, i relativi pagamenti nonehé future rimozioni in seguite a licenziamenti efo termini di collabor Ma solo questa classe non ® sufficiente a caratterizzare il sistema arienda nellinterezza e, infati, 2 il caso di suddividere tutto il Nome Cognome Indirizzo Data di nascita Codice Fiscale Assumi Licenzia Paga Collaboratori Attributi Metodi | (Fig. 1» Schema di principio i una generica classe Collaboratori ;chema di principio della gerarchia personale in Consulenti e Dipendenti poiché, come noto, hanno prerogative differenti. I Consulensi hanno ad esempio una partita IVA e una retribuzione tariffaria mente i Dipendenti si differen- iano poiché hanno uno stipendio lordo mensile (e quindi anno), trattenute fiscali e contributi assistenziali, Ma ancora non abbia- ‘mo terminato perché lattuale astrazione del personale & ancora ficitaria, infatti dobbiamo distinguere la classe dei dipendenti in almeno ulteriosi we categorie: Dirigenti, Impiegati e Segreta- Fi, Perché questa ulteriore differenziazione? A fronte di elementi ‘comuni (nuovi inserimenti,licenziamenti eve) queste ulteriori tre categorie sono soggette a specifiche voci individuali. Ad esempio, il calcolo degli straordinari va applicato solo ai dipendenti ma non ai difigenti cosi come le procedure di pagamento vanno differen- L'OGGETTO CLASSE ao ne eer class None Classe (Supereiasse1,1 ‘Superclaase2, ...,Superciassex) secrusione? istruzionea seal OPERATORI ARITMETICI Non solo le 4 operazioni In Python gli operatoriaritmetici fondamentati possono assumere due forme. La modalita “classica” vede li ‘usuali operatori di somma +, sottrazione -, moltiplicazio- ne *, resto di una divisione % e elevamento a potenza **. Esistono situazioni dove farebbe comodo avere funzioni in uogo ai operators cid & possibile uttizzando il modulo ‘operator i cui metodi vedono, rispettivamente, addlx.yl, sublx.yl, mullx,y1, modlxyl e powlx.yl, impartire it co- ‘mando helpl'operator' per ulterior! funzion|. Volutamente ‘non abbiama considerato la divisione la cui funzione @ divtxy), truedivixy! in Python3, per Uoperatore / che ritorna la divisione comprensiva di resto in Python3 e la divisione troncata in Python2 in caso di operandi interi, altriment un risultato float (in presenza di operandi float). Infine ta funzione floordiv(x.yl per \'operatore // di divi- sione intera la quale tronca sempre i resto sia in Python2 che in Pythons riternando un intaro se gli operandi sono interi,altrimenti dei float. ‘hate a seconda della categoria di dipendenti nonché tra consulenti € collaboratori TLo schema generale & visibile in Fig. 2. Se volessimo serivere del eodice per questa organizzarione uziendale potremmo scrive re una nuova classe da zero ad-hoc per ogni singola categoria, ‘oppure. se contempla clementi comuni con una classe gid scritta c/o built-in, possiamo derivarla da essa. In questi casi, si parla di ereditarieta e si dice che la nuova classe, definita in questi casi sttoctasse, eredita tuti gli att perla classe di cui &erede (nota anche come classe hase o superclasse) Poiché una sottoclasse @a sua volta una classe, da essa si potranno, e il suo namespace rettangolo,_diet_risultera(), ovvero un dizionar ‘voto! Ma cos’ il namespace? Quando una classe viene definit, creato un nuovo namespace, pertanto tutti gli assegnamenti che avvengono negli attribute nei metodi vanno a riempire que- sto nuovo spazio dei nomi con la carateristica che non &8 alouna relazione tra nomi uguali in differenti namespace. Quiadi, ogni assegnamento elo definizione di funzione viene memorizzato in ‘un attribato speciale di nome _ diet _e defiisce uno spszio che prende il nome di namespace, un dizionario che ha l'usuale forma peri dizionar, la coppia nome:valore, Allor,richiedere il valo- re di un nome contenuto nel namespace equivale a richiedere un ‘alore in un dizionario. In funzione del contest potremo avere la necessiti di aceedere al namespace usando Veperatare * (punto) ‘oppure come variable locale. Iniziamo ad abbozzare un possibile corpo della classe Poligono la quale, ad esempio, potra essere vi stu come la classe base (la superelase) peri calcolo del perimetro € dell'area di figure geometriche in due dimensioni: class Poligono abject} variei0 def _inie__(eelf, numere_lati): self munero, latismuneyo lati elt latis{0 for 4 in range (mere laei!) ‘Se rimaniamo all'interno del namespace della classe non &® neces- sith alcuna di utiizzare Yoperatore “”, viceversa appena usciamo dal ambito di visiblita locale ne dobbiamo fare uso. Seriviamo le poche righe riportate nelVimerprete interattivo. Per accedere alla variable varl dalfesterno della classe utilizzeremo V'operatore “.” con Poligono.yarl il cui risultato sara il valore della variabile ABH ame ITERATORI: 3.X VS 2.7.X POE fetaenrts Classe istanze di una classe hanno distini namespace e la rego- 1a di risolurione & simile alla LEGB che abbiamo definito nello scorso appuntaiento: quando un nome non viene trovato nel na espace dellstanza allora Python va a vedere nel namespace del- Ia lasse e, se non presente, viene sollevata una eccezione. In pid, analogamente a LEGB, un assegnamento in una istanza nasconde una eventuale variabile dello stesso nome presente nella classe. Ad cesempio,serivendo t=Poligono(3) possiamo trovate mumero_tati nel namespace delstanca tnumero lati con risultat 3, come & facile verficare con t__dict_che fornisce {at (0, 0, 0}, ‘na ‘mero lati’: 3} e nel quale notiamo Iassenza della variabile var Ma se provassimo a date var avremo come rsultato 10 ovvero verraricercata nel namespace della classe Poligono: al soito, per la verifica uilizzare il comando Poligono._diet_. F evidente allora come ttt le istanze hanno accesso agli atrbuti della clas- se: ad esempio lstanza rettangolo=Poligono(4) avra essa stessa accesso a varl come & facile veriticare (rettangole.vart), Infine, Se provassimo a imparie t.var2 otterremo un eloguente Attel- buteError: 'Poligono’ object has no attribute 'var2' ovvero la non esistenza di aleun atcibuto di nome var2 nellambito di vsibi- Tia prima dellstanza poi della class. In definitiva il namespace det istanza hala precedenca sul namespace della clase e see un ‘nome uguale in entrambi i namespace viene preso in considerazio~ ne quello delstanza ESEMPIO DI CLASSE Scriviamo nelimerpreteinterattivo tuts la classe Poligono, ricordan- doc di rispettare Vindentazione del codice: class Poligeno (cbject) : def init__(self, munevo lati) Lf mmimero_latianimere_lati self Lati-[0 for 1 in range (aupero ati! ef inseriscitati {self} : self lati=|float (input ("Inserisci lato "estr(ist)+1 "2 "7 for £ im range self.nmero atl) late "yi," ha una lunghasza 4i2 mj sel latéli)) Dopo la definizione di classe con la keyword class ¢ relative nome, ‘hon teoviamo aleun attributo ma il primo metodo della classe. Se si tende necessario inizializzare aleuni zare il metodo init quello che in altri lingu pio in C++) & noto come il costruttore della classe, Ni Python non esiste un costruttore e il metodo _ init, definito pit! un “inizializzatore” poiché impone il passaggio degli argomenti all'ato della chiamata, ad esempio nel momento in cui ppud essere andiamo ad istanziare Ja classe utilizzando i perametsi presenti ta parentesi, Possiamo inizializzare i parametri all'interno della parentesi previo assega: riamo le nento ma qualora non Jo fossero e chia lasse senza parametti verta sollevata una eccezione del tipo TypeError:_init__() takes exactly 2 arguments (1 given) 1 primo parametzo di ogni metodo di una classe deve essere la keyword self la quale rappresenta un riferimento all oggettoistan ziato: Le suc; lizzazione, due nuovi oggetti di nome numero_lati conflitto ta 'attributo self.numero_lati ssive due ¢ he definiscono, nel metodo di inizia- lati, Non ce ero_lati e V'ttributo mu poiché loperstore (la notazione) punto ”.” specifica a quale varia bile ci sista riferendo. Terminata di scrivere la classe nell'inte “ligono(4) indo cosi un'stanza della. classe Poligono con i due attributi mero lati ¢ lati come & facile verificare con Quadrato,_ dict. A questo punto inseriamo la lunghezza dei lati con Qua- drato.inserisei pre te interattive, scriviamo Tassegnamento Quadrat iQ che chiama in causa Yomonimo metodo i quale non si aspetta alcun argomento, ¢ infatti se provassimo a passargliene uno vera sollevata una eccezione. Osserviamo come non abbiamo seritto self il quale viene passato implicitamente da 1 Quadrato. Allo stesso modo possiamo richiamare il metodo stampaLati() con Quadrato.stampal ati() che visualizzer’ la lunghezza dei lati inseriti (Fig. creato la forma, Vabbiamo soltanto d Python: in questo esempio, self & riferito alist 3), Con la classe Poligono allora non abbiamo poi, sara possibile specificarla con una classe dedicata, sottoclasse i Poligeno, EREDITARE DAI PARENTI! Non chivdiamo ancora Vnterprete interattivo e scriviamo la se guente classe la quale sara decivata dalla classe Poligono come visibile nella prima riga: etdig’ 124 dngolo (761 igona! Poligone def calcolatrea(eait) a/b, c=sel£. Tati Derimetre del triangole e! 40.26 re l'area equivale a: * ¥isp,area)! Questa classe ci definisee un poligono con 3 lati quindi un “poligono. 0 un tiangolo) nella quale andiamo a calcolare «© come lo faceiamo? Senze riscriverealcuaché di co- ben preciso” (d perimetro ea dice sui lati ma richiamando la classe Poligono che al suo interno ha gid i metodi per Vinizilizzazione, Vnserimento ¢ la visualizzazione dei lati in sostanza,ereditando metodie abut della classe Poligono « specializzando la classe Triangolo solo peri calcolo dei dai di inte resse previo inserimonto di un nuovo meted di nome ealcolaArea() che a sua volta potra essere utlizzato da una istanza della classe Tian golo. Scopriamo come Creiamo unistanza con T=Triangolo() 1a quale richiama la clas se Poligono passandole 3 come numero di lat: verranno creati i due autributi numero lati ¢ lati (verificarla con T._ diet fra 1s lunghez7a dei lati richiamando il metodo di inserimento con ‘TinserisciL ati() che & stato ereitato dalla classe Poligono a cui fac: ciamo seguite la visualizzazione dei lat T.stampaLati(),Infine cake: i aN a aD CONVERSIONE DATI Rappresentiamo i risultati Net corso di queste puntate abbiamo visto come sia pos- sibile rappresentare i risultati di un dato programma con Uistruzione (una funzione in Python3} print. In determinate ceccasioni, ped, esistone situazioni dove la rappresen- tazione normale mal si presta alla visualizzazione diun certo tipo di dati. Python offre alcuni metodi per migtio- rare la situazione e uno di questi é__str__che quando inyocato [come nei sorgenti di questo mese] effettua una ‘conversione a stringa del\’oggetto fornendo informazioni pil “user-friedly” per utente, Al contrario, se occorrono Informazioni pid utili ai programmatori, viene utilizzato il metodo _repr__che, quando invocato, da origine ad una rappresentazione dell'oggetto, roost 3298 (S Fig. 4» Ereditarieta muttipta da due classi, mail concetto & estensibile aN classi liamo area richiamando il metodo ealeolaArea() con T.ealeolaArea() che riporter perimetroe area del triangolo come visibile in bass in Fi ‘gura 3. Entrambe le classi le si potranno provare nellinterprete Python in versione 2 ¢ 3, Due osservazioni per concludere questo paragraf, [Nellassegnare i tr lati nella classe Triangolo abbiamo fito uso di un ‘unpacking ovvero Fassegnamento di pid elementi a pi varabili utili “zando una sol istruzione. Per area del range, poiché abbizmo solo la Tunghezza dei late nessunalrainformazione, in luego dela ben pid nota (hase“alterza)/2 abbizmo utilizato la formula di Erone nla quale si fa riferimento al semiperimetio(perimetro diviso 2). La formula in presenza lati ab ee i lungherza nota, vede il valore delaea pai a: A= \sp*|sp—a)*|sp—b]*|sp—c] dove sp il semiperimetro, EREDITARIETA MULTIPLA Nel paragrafo precedente abbiamo ilstrato un semplice esempio di ere- slarieta di una classe. Python permette ereditaretA mulipla: una classe ‘ud creditare atributi€ metodi da 2 0 pit classi anche non correlate ta loco. Prendiamo come esempio il seguene code, che non fa nulla ma serve aillusrare le propriet dell ereditarieta multipla class Alobject} : pees clase B(ebject) pass clase c1Ri8) pass Por matvi di spazio non abbiamo riper tribute metodi nelle classi ma, ipotizzando la situazione in Fig. 4, osserviamo come la classe A la classe B risultano indipendent ra loro e contengono un certo numero di atibus e metodi, Anche Ia claste Cha atibut e metodi propre in pit evedita dalla classe Ac dalla classe B gi associat attribute metod. Se andiamo a creare una istanza della classe C del tipo oggetto=C) potremo accedere al metodo AI della classe A con oggetto.metodoA I) ¢ analogamente perl classe B con oggetto.metodoB2). Nellpotes,a dire il vero non proprio reali- sticache meted nelle tre clasiavessero rut lo tesso nome, varrebbe fa Toga del namespace. Ad esempio, se la classe C (quella che implementa Tereditd multpla) avesse un metodo definito anche in una delle super lassi, 0 in entrambe, vert invocata la definizione presente nella classe cereitata, Vioeversa vera uilizata la gerarchia di ereditrieth della classe ANCORA SUI MODULI import vs from: quale utilizzare? ‘Sapplamo come importare un modulo utilizzando 'istruzione import che, loricordiamo, ordina al'nterprete di trovare nome_ ‘moduto,py e, se non & mai state trovato prima, di compilarto in un file pyc ed eseguiro, Solo a questo punto possiame accedere al ‘namespace del modulo importato owero ai suo attribute metodi. Python, perd, permette di importare anche solo alcune funzioni di ‘un modulo nel namespace corrente. L'uso difrom potrebbe sem- brare un‘attima idea ein realta lo é ma solo se se ne fa un uso molto _accorto owero se si rendone vsibilia import * solo i nomi uti a chi poi andra richiamare il modulo: questo é possibile escludendo ‘nomi global facendoliniziare con il carattere underscore ~_" oppu~ redire esplicitamente aimport * quali nomi importare uiizzando ‘un modulo copiandole nel namespace corrente attraverso la sintas~ il metodo _all__, Se non si prendone queste precauzioni si rischia sifrom nome_modulo import nome_metodo, Con sintassi analoga, from nome_modulo import, @ possibile importare tutti nomi ¢i «i vanificare il sistema dei namespace in Python progettato proprio perevitare situazioni di confltto! che vede dapprima la ricerea nella lasse A. poi nella classe B. Se i metodo invocato non dovesse esstre né nella classe ereditatae nemmeno nelle due superclass ver sollevata una eecezione. AUMENTIAMO LA COMPLESSITA! Nei filed esempio (searicabil dalfindirizao htdigoa.g/SHkkantcovece mo te file che provvederomé 2 copie in una eartella nella nostra. home ‘utente: in Fig. 5 visible OrologioCompleto.py, Ricordiamo che quando siscrive un file sorgenein Python clo si prova a lancire facile incappae, soprateto peri meno expert chi sta inigiando a stadire it Python, in ror del tipo TabExror: inconsistent use of tabs and spaces in indent. tion, In queso caso si verfchi sempre se sono stati mischiatetbulazionie spr bianchi en prticolare, lt coerenza nelle indentaziont I programma nella sua interezza non fa nulla di sconvolgente, ra e permet di ampliane le nostra conoscenzasullinterazone di file in programm che ne prevedono diversi come & ka norma in pro st.con un minim di complessia! Nel prowsimo appuntamento scopriremo come ec pplcarion pt pratiche Abia gf ripe raf in pit ale sono rporate ato tte le osservarioni novessare nei precedent para omimenti de sngent pe ro se non che simula un semplice 24 Dicembre del 1957 salforologio, metodo Tempod),¢ sl alendario, metodo Avanza() che pocter il calendar al 3 molto da aggiungere sul suo funziona ‘orologio con snsesso 21212 vi \dario ee partendo dal iterata 10 volte la chiara alle ore IMPORTATO O ESEGUITO? eee iat) Peete | importarlo in unaltro fle sorgente c/o esequitodirettamente ot ees Come facclamoa capire quando'siamo In una on ea CO ume ee eUentse es aetd etre eee ceed Ree a at eee een Gennaio 1988 alle oe 12:12:22, ii avanzament dell rae della data non sono correla tea loro pertanto si ptr terre 100 vole a chiamatasulforae 1000 volte quella sulla data In pit, poich¢ le ore i minut i secondi sone inizislizzati nel metodo init__ di OrologioCompleto.py possiamo cambiare Ia dated inizio ‘coi come rimuevere Foraro alla riga 22 senza per questo incorere alcuna eccezione: & evidente come in questo caso Vorario partir dalla ‘mezzanotte (00:00:00) Per teminarericordamo che problemi, delucida zioni e domande varie sul argomento possono essere rportae ne forum i Linux Magazine (www dinux-magazine forum) ew Ble Modifica e-o> ‘Tenpo inport Orologio 8 Calendario import Calendario Visualize yal Segnalibri Strumenti Lass Orologioconpleto (Orelogio, Calendario) © def _init__ (2014, giorno,nese, anno, ore Calendari9.-init(se\, giorno, nese, anno) Orotegic,. init Teel, ore, minus, seconds) © Get _str_(sel?) return "Data: "4Calendario._str_(selt)« +"0re: ‘OrologioCompleto.py - Konqueror wale Collaborative &~ @ GO B~1A SF Fromeiichanmoicaiendes v) fp & ° Impostazioni Finestra Aiuto > | minuti=0, second = '40rologio._str_ (self 5+ Inalto una parte: 3 sorgente, in basso a sua esecuzione

Potrebbero piacerti anche