Python base - alfredocentinaro.it https://www.alfredocentinaro.it/category/lezioni/python/python-base/ Sito personale di Alfredo Centinaro, ingegnere informatico, insegnante, musicista. Programmazione, appunti, esercizi, sistemi e reti, tpsit, esami di stato, arduino Wed, 14 Jan 2026 19:16:30 +0000 it-IT hourly 1 https://wordpress.org/?v=6.9.4 https://www.alfredocentinaro.it/wp-content/uploads/2022/01/logo_alfredocentinaro-150x150.png Python base - alfredocentinaro.it https://www.alfredocentinaro.it/category/lezioni/python/python-base/ 32 32 Annotazioni di tipo in Python https://www.alfredocentinaro.it/lezioni/python/python-base/annotazioni-in-python/ Tue, 21 Oct 2025 22:18:01 +0000 https://www.alfredocentinaro.it/?p=8631 Python è un linguaggio molto facile da apprendere anche per i non informatici, grazie alla pulizia della sua sintassi, alla non tipizzazione dei dati e all’eliminazione di molti elementi ostici come punti e virgola, tipi di ritorno espliciti, ecc. In realtà, quando facciamo scripting rapido, queste caratteristiche sono molto desiderabili, ma se ci imbarchiamo in ... Leggi tutto

L'articolo Annotazioni di tipo in Python proviene da alfredocentinaro.it.

]]>
Python è un linguaggio molto facile da apprendere anche per i non informatici, grazie alla pulizia della sua sintassi, alla non tipizzazione dei dati e all’eliminazione di molti elementi ostici come punti e virgola, tipi di ritorno espliciti, ecc. In realtà, quando facciamo scripting rapido, queste caratteristiche sono molto desiderabili, ma se ci imbarchiamo in codice più complesso e strutturato, avere degli ausili per tenere traccia dei tipi di dato nei parametri potrebbe essere vincente. Per questi motivi, dalle versioni 3.5 e 3.6 sono state introdotte delle annotazioni di tipo (type hints), non obbligatorie, che non vengono utilizzate in fase di parsing/compilazione ma sono preziose per una lettura facilitata del codice. Vediamone alcune utili per il livello scolastico.


Ci sono anche alcuni plugin come Pylance di Visual Studio Code che leggono le annotazioni e danno suggerimenti non bloccanti utili allo sviluppatore. Pycharm, da IDE strutturato, è già compatibile.

Tipi di variabili

Il tipo di variabile sappiamo non essere obbligatorio, ma possiamo annotare il contenuto che verrà posto in fase di inizializzazione contestuale o semplicemente successiva. Attenzione alla seconda dicitura: se provo a stampare pluto mi darà comunque errore di variabile non inizializzata; l’annotazione non dà nessun valore predefinito.

pippo = 10   #classico
pippo: int = 10   #con annotazione

pluto: int   #errore

Ovviamente si possono usare i tipi floot, str, bool, meno usati bytes e Any.

Il tipo Any è particolarmente utile quando non sappiamo quale tipo di dato riceveremo, ma andrebbe usato con parsimonia perché vanifica i vantaggi delle annotazioni.

from typing import Any

dato_generico: Any = "potrebbe essere qualsiasi cosa"
dato_generico = 42  # nessun problema

Liste e dizionari

Anche su dati strutturati le annotazioni ci aiutano, almeno in fase di dichiarazione.

nomi: list[str] = ["pippo", "pluto"]    # lista di stringhe
eta: dict[str, int] = {"mario": 30}     # dizionario con chiavi string e valori int
numeri: list[int] = [1, 2, 3, 4, 5]     # lista di interi

Funzioni

Sicuramente le annotazioni più interessanti sono quelle del tipo di ritorno nelle funzioni. Python, sappiamo, può restituire uno o più valori semplicemente ponendo la parola return seguita da una o più variabili, di cui viene passata la copia. Nella definizione della funzione si riconosce solo la parola chiave def e i parametri; non è infatti necessario specificare di quale tipo (int, string, char, ecc.). Nello scripting veloce è comodo e desiderabile tale semplificazione, ma in un codice con classi e numerosi metodi/funzioni può risultare utile specificarlo.

def potenza(base: int, esponente: int = 2) -> int:
    return base ** esponente

def saluta(nome: str) -> str:
    return f"Ciao, {nome}!"

#funzioni senza ritorno
def stampa_messaggio(testo: str) -> None:
    print(testo)

Attenzione: Python può restituire anche più di un valore per funzione, ma non c’è un’annotazione diretta, quindi si usa il tipo tuple.

def coordinate() -> tuple[int, int]:
    return 10, 20

def dati_studente() -> tuple[str, int, float]:
    return "Mario", 18, 7.5  # nome, età, media

Interessante è la possibilità di un ritorno di tipo alternativo, magari condizionato da un’istruzione if. Occhio, potrebbe essere una pratica pericolosa in molti casi, da usare con cautela

def valore(x: str) -> int | None:
    if x.isdigit():
        return int(x)
    return None

L'articolo Annotazioni di tipo in Python proviene da alfredocentinaro.it.

]]>
Introduzione alla OOP in Python https://www.alfredocentinaro.it/lezioni/python/python-base/introduzione-alla-oop-in-python/ Thu, 06 Nov 2025 09:32:22 +0000 https://www.alfredocentinaro.it/?p=8627 Questo articolo vuole introdurre ai pochi elementi fondamentali per utilizzare la OOP in Python per frammenti di codice prevalentemente pensati per i corsi di informatica di scuola superiore. Vi rimando a guide più articolate per conoscere dettagli in modo più specifico. La OOP in Python Python nasce come linguaggio di scripting, per sviluppi spesso semplici ... Leggi tutto

L'articolo Introduzione alla OOP in Python proviene da alfredocentinaro.it.

]]>
Questo articolo vuole introdurre ai pochi elementi fondamentali per utilizzare la OOP in Python per frammenti di codice prevalentemente pensati per i corsi di informatica di scuola superiore. Vi rimando a guide più articolate per conoscere dettagli in modo più specifico.

La OOP in Python

Python nasce come linguaggio di scripting, per sviluppi spesso semplici e con relativamente poche righe di codice da gestire. La mancanza di un programma main ne certifica ulteriormente questo scopo. Nel corso del tempo e della diffusione Python è sempre più utilizzato in progetti complessi ma a quel punto il paradigma semplicistico dello scripting comincia a a scricchiolare: occorre la programmazione orientata agli oggetti (OOP).

Le classi

Se abbiamo studiato un linguaggio OOP come Java e C#, alcune caratteristiche delle classi i Python ci potrebbero sconvolgere ma nell’ottica di semplificare, tutto appare più evidente. Alcune dinamiche possono essere reimplementate analogamente agli altri linguaggi ma occorre abbandonare lo standard aggiungendo altre librerie.

In python non si dichiarano in una sezione su misura gli attributi. Tutto viene fatto direttamente il quello che è di fatto il costruttore. Tale metodo non ha il solito nome della classe ma ha la dicitura __init__(self) per il costruttore standard, seguito da eventuali parametri per valorizzare inizialmente gli attributi in una istanza. Bada ben, ogni metodo associato d una classe come primo parametro ha sempre il self che equivale un po’ al this degli altri linguaggi Java/C++.

class Alunno:
    def __init__(self, _nome, _cognome):
        self.nome = _nome
        self.cognome = _cognome
    
    def stampa(self):
        print("Alunno: ", self.nome, " ", self.cognome)

if __name__ == "__main__":
    alfredo = Alunno("Alfredo", "Centinaro")
    alfredo.stampa()
    print(alfredo.nome) 

Come già si intuisce dal frammento di codice: pyhton non distingue attributi privati, pubblici o protetti. Tutti gli attributi sono pubblici violando il concetto di incapsulamento della OOP. Possiamo pur sempre andare a creare i metodi di accesso set/get ma anche a voler cercare qualcosa di simile abbiamo la possibilità di mettere due underscore davanti al nome self.__nome per indicare quell’attributo come offuscato, da non gestire direttamente ma pur sempre visibile come alfredo._Alfredo__nome quindi più complesso da scrivere ma senza reale vantaggio. In pratica il programmatore che sceglie questa modalità da semplicemente un avvertimento nell’accesso diretto.

Metodi

Come intuibile, i metodi sono delle banali funzioni ma con il parametro self iniziale obbligatorio. Le funzioni sono tutte pubbliche. L’unica accortezza è magari di utilizzare le annotazioni (leggi qui) per rendere il codice commentato e meglio leggibile. Vediamo una manciata di esempi per completezza:

def stampa(self):
    print("Alunno: ", self.nome, " ", self.cognome)

def getNome(self):
    return self._name

def setNome(self, _nome):
    if isinstance(_nome, str):
       self.nome = _nome
   else:
       return

def setPrelievo(self, _denaro):
    if self.conto > _denaro:
        self.conto -= _denaro
    else:
        return

Overloading dei metodi

L’overloading non è possibile in modo esplicito in Python, altra stranezza contro il mondo OOP. E’ possibile fare overloading solo del costruttore __init__. Nel codice sopra, se volessi un metodo stampa(self) ed uno stampa(self, _saluto) non posso realizzarlo esplicitamente. Possiamo provare a mettere parametri inizializzati a None o usare un trucco con la libreria from typing import overload ma nulla ci consente un vero overloading. Bisognerà esplicitamente creare metodi separati o passare eventualmente un vettore/lista di parametri da validare ed utilizzare rendendo il codice più complesso.

class Alunno:
    def __init__(self):
        self.nome = ""
        self.cognome = ""

    def __init__(self,  _cognome):
        self.nome = ""
        self.cognome = _cognome

    def __init__(self, _nome, _cognome):
        self.nome = _nome
        self.cognome = _cognome

L'articolo Introduzione alla OOP in Python proviene da alfredocentinaro.it.

]]>
Gara di salti in Python https://www.alfredocentinaro.it/lezioni/python/gara-di-salti-in-python/ Sun, 29 Dec 2024 21:26:24 +0000 https://www.alfredocentinaro.it/?p=8182 Un esercizio dalla complessità più interessante per esplorare ed applicare le nozioni base di Python dall’uso dei file, le strutture dati come liste e dizionari (puoi ripassarli qui), cicli, funzioni, numeri casuali. Vogliamo simulare una gara di salto in lungo. I nomi degli atleti vengono caricati in una lista leggendo un file di testo, in ... Leggi tutto

L'articolo Gara di salti in Python proviene da alfredocentinaro.it.

]]>
Un esercizio dalla complessità più interessante per esplorare ed applicare le nozioni base di Python dall’uso dei file, le strutture dati come liste e dizionari (puoi ripassarli qui), cicli, funzioni, numeri casuali.

Vogliamo simulare una gara di salto in lungo. I nomi degli atleti vengono caricati in una lista leggendo un file di testo, in cui i nomi sono posti uno sotto l’altro. Successivamente il software deve simulare tre salti per ogni atleta lanciando un numero casuale compreso tra 6.00 e 9.99. Il salto può inoltre essere nullo con una probabilità del 50% in stile testa o croce e quindi in questo caso risulta una misura pari a zero. Le misure dei salti devono quindi essere archiviate per ogni atleta in un dizionario opportuno. La seconda fase della gara prevede che a passare siano solo i primi 8 ad aver totalizzato i salti più lunghi tra i tre a disposizione. Degli 8 vincono e vengono stampati i primi 3.

Lettura del file

Come ogni esercizio più complesso che si rispetti, c’è una interazione/caricamento di dati da file. Per abitudine su questo sito web, creiamo sempre una funzione su misura che ci restituisce una lista con i contenuti cercati e caricati. La chiamiamo leggiFile e usiamo il decoratore non obbligatorio ->list per tenere a mente il tipo di ritorno.

Usiamo il costrutto with per evitare le operazioni di try/catch e la necessità di chiudere esplicitamente il file con il comando close().

nomefile = "atleti.txt"



def leggiFile() ->list:

    lista = list()
    with open(nomefile, "r") as file:
        righe = file.readlines()
        for riga in righe:
            lista.append(riga.rstrip("\n")) #rstrip ripulisce andata a capo \n

    return lista

Appendere, ovvero aggiungere i nomi letti ad una lista è semplice ma c’è un dettaglio che spesso rende ardua la vita dello studente alle prime armi. Il file di testo ha un carattere jolly per indicare l’andata a capo che inevitabilmente verrebbe letto assieme al nome. Così lo rimuoviamo con la funzione rstrip in fase di lettura. Esistono anche altri modi per liberarsi del carattere \n.

La funzione per simulare il salto

Prepariamo una funzione per simulare il salto del singolo atleta. Anche qui uso il decoratore ->float Abbiamo bisogno di utilizzare il modulo random da cui possiamo importare solo le funzioni randint e uniform: la prima stacca numeri interi, la seconda numeri decimali in un determinato intervallo assegnato.

Per trovare se il salto è nullo o valido lanciamo una sorta di testa/croce con due numeri 0 e 1. Se esce zero assumo che il salto sia nullo, se 1 vado a trovare la misura del salto. Per il salto lanciamo un secondo numero casuale questa volta decimale invece che intero. Una tragedia del python è gestire i numeri decimali che vengono presentati con molte cifre. A noi occorrono spesso solo le prime due, così effettuiamo un preventivo arrotondamento con round.

from random import uniform, randint

def simulaSalto() -> float:
    
    valido = randint(0,1)
     
    #se esce 0 salto nullo
    if valido == 0:
        return 0
    
    #esce 1, scelgo un numero tra 6 e 9
    salto = round(uniform(6.00, 9.99),2)
    return salto

Il corpo principale

Siamo pronti per creare il nostro programma principale che consigli sempre di differenziare con il if __name__ == “__main__”: per tenere ben separati funzioni, variabili globali, import vari dal corpo centrale del programma.

Qui dobbiamo procedere a chiamare la funzione di caricamento del file. Quindi procediamo a far saltare tre volte ogni atleta della lista e salviamo tutto in un dizionario. Qui il vantaggio di usare python forse è più visibile se usiamo la proprietà di assegnazione di una intera lista con tanto di valori random richiamati in fase di inizializzazione della stessa. Ci sono modi anche più semplici e tradizionali ovviamente per fare la stessa operazione. Stampiamo il risultato finalmente.

    gara = dict()
    for atleta in listaatleti:
        gara[atleta]= [simulaSalto(), simulaSalto(), simulaSalto()] 

Alla seconda fase però partecipano soltanto i primi 8, tra quelli che hanno saltato ovviamente più lontano in modo assoluto e su salto singolo. Ora sta nel trovare per ogni atleta il suo salto massimo tra i tre che ha effettuato. Conviene usare una nuova struttura dizionario dove salvare come chiave ancora il nome e il valore del salto massimo. Ennesimo vantaggio di python è che fare il max di un vettore lista di 3 valori è semplicissimo con la chiamata max() con il vettore associato all’indice del nome atleta come parametro.

    massimi = dict()
    for atleta in gara:
        massimi[atleta]=max(gara[atleta])

Per controllo possiamo stampare quindi il massimo di ogni atleta appena trovato.

Siamo alla parte più complessa dell’esercizio: trovare i primi 8 atleti ad aver saltato più lontano tra i massimi appena individuati. Non c’è una sola soluzione ovviamente ma ne proponiamo una dove scorriamo tutti i valori possibili dei salti da 9,99 a 0,00 spostandoci di decimale in decimale con passo 0,01. Ad ogni possibile misura controlliamo se gli atleti hanno tra i loro salti massimi la misura in considerazione. Se ci sono atleti corrispondenti li inserisco in un nuovo dizionario nome/misura salto e mi decremento un contatore di 8 posi disponibili. Quando ho analizzato tutte le possibile misure o ho già piazzato 8 atleti, esco dal ciclo. Avremo gli 8 atleti con i salti tra l’altro ordinati!

#scorro tutte le misure possibile da 9.99 a 0.00
    #controllo se ci sono atleti corrispondenti a quella misura/salto
    #se trovo un atleta lo inserisco in nuovo dizionario
    #scalo 1 posto disponibile degli 8 ammessi
    secondafase = dict()
    numeroatleti = 8
    misura = 9.99
    while misura >= 0.00:
        for atleta in massimi:
            if massimi[atleta] == misura:
                secondafase[atleta] =massimi[atleta]
                numeroatleti -= 1
        if numeroatleti == 0:
            break
        #occhio alla sottrazione float che ha sempre cifre decimali sporche
        #9.99 - 0.01 non fa 9.98 
        misura = round(misura - 0.01,2) 

Listato completo

from random import uniform, randint


nomefile = "atleti.txt"


'''
FUNZIONI
'''

def leggiFile() ->list:

    lista = list()
    with open(nomefile, "r") as file:
        righe = file.readlines()
        for riga in righe:
            lista.append(riga.rstrip("\n")) #rstrip ripulisce andata a capo \n

    return lista




def simulaSalto() -> float:
    
    valido = randint(0,1)
     
    #se esce 0 salto nullo
    if valido == 0:
        return 0
    
    #esce 1, scelgo un numero tra 6 e 9
    salto = round(uniform(6.00, 9.99),2)
    return salto



'''
MAIN
'''
if __name__ == "__main__":
    listaatleti = leggiFile()
    
    
    '''
    PRIMA FASE: faccio saltare 3 volte tutti gli atleti e li immagazino in un dizionario gara
    '''
    gara = dict()
    for atleta in listaatleti:
        gara[atleta]= [simulaSalto(), simulaSalto(), simulaSalto()] 

    print("|-----------------------------------------------------------|")
    print("|                     RISULTATO SALTI                       |")
    print("|-----------------------------------------------------------|")
    for atleta in gara:
        print(f" ATLETA: {atleta} - SALTO 1: m{gara[atleta][0]}, SALTO 2: m{gara[atleta][0]}, SALTO 3: m{gara[atleta][0]}")
    
    print("")

    '''
    SECONDA FASE: prendo i primi 8
    '''
    
    #Scorro i risultati di ogni atleta e dei 3 prendo il massimo. 
    #Metto i massimi in un dizionario atleta/salto quindi    
    massimi = dict()
    for atleta in gara:
        massimi[atleta]=max(gara[atleta])

    print("|-----------------------------------------------------------|")
    print("|                  SALTO MAX PER ATLETA                     |")
    print("|-----------------------------------------------------------|")        
    for atleta in massimi:
        print(f" ATLETA: {atleta} - SALTO MAX: m{massimi[atleta]}")
    print("")

    #scorro tutte le misure possibile da 9.99 a 0.00
    #controllo se ci sono atleti corrispondenti a quella misura/salto
    #se trovo un atleta lo inserisco in nuovo dizionario
    #scalo 1 posto disponibile degli 8 ammessi
    secondafase = dict()
    numeroatleti = 8
    misura = 9.99
    while misura >= 0.00:
        for atleta in massimi:
            if massimi[atleta] == misura:
                secondafase[atleta] =massimi[atleta]
                numeroatleti -= 1
        if numeroatleti == 0:
            break
        #occhio alla sottrazione float che ha sempre cifre decimali sporche
        #9.99 - 0.01 non fa 9.98 
        misura = round(misura - 0.01,2) 

    print("|-----------------------------------------------------------|")
    print("|                   PODIO ATLETI SALTO                      |")
    print("|-----------------------------------------------------------|")        
    for indice in range(0,3):
        atleta, salto = list(secondafase.items())[indice]
        print(f" ATLETA: {atleta}, m{salto}")
    
    pass

Peri l file abbiamo semplicemente creato il file txt ed inserito nomi di personaggi di topolino, uno sotto l’altro.

L'articolo Gara di salti in Python proviene da alfredocentinaro.it.

]]>
Le funzioni in Python https://www.alfredocentinaro.it/lezioni/python/python-base/le-funzioni-in-python/ Tue, 28 May 2024 11:00:32 +0000 https://www.alfredocentinaro.it/?p=7683 Argomento sicuramente molto ben trattato nella manualistica online e scolastica. Ci limitiamo alle generalità ed alcuni dettagli magari più sfiziosi da trovare nei corsi base. Le funzioni in Python, come tutti i linguaggi di programmazione, sono veri e propri sottoprogrammi che suddividono e scompongono un problema più grande in problemi più piccoli. Le funzioni hanno ... Leggi tutto

L'articolo Le funzioni in Python proviene da alfredocentinaro.it.

]]>
Argomento sicuramente molto ben trattato nella manualistica online e scolastica. Ci limitiamo alle generalità ed alcuni dettagli magari più sfiziosi da trovare nei corsi base.

Le funzioni in Python, come tutti i linguaggi di programmazione, sono veri e propri sottoprogrammi che suddividono e scompongono un problema più grande in problemi più piccoli. Le funzioni hanno il grande vantaggio di permettere una gestione del codice più atomica sia per una comprensione migliore, debug più snello, sia per una manutenzione e modifica più semplice.

Come si dichiara

Essendo Python un linguaggio ad alto livello non tipizzato, le funzioni non hanno un tipo di ritorno ma la loro dichiarazione si limita ad una parola chiave def.

def nomeFunzione(parametro1, parametro2, ...):
    """
    Docstring: descrizione della funzione.
    """

    # bla bla di codice

    return valore

Questa seguita è dal nome della funzione che, non smetterò mai di ricordarlo agli alunni, non deve mai avere parole staccate ma una sola parola che descriva in modo coerente lo scopo della funzione. Potete usare l’italiano o l’inglese, evitate numeri nel nome o elementi che caratterizzano un esempio di uso della funzione stessa. Evitate le lettere accentate, esistono solo in Italia e pochi Paesi.Sono ammessi nome tipo isPari, get_nome, setCognome, con mix di maiuscole e minuscole o il trattino basso. Siate sobri nel nome: se leggete o qualcuno legge il codice il nome deve essere chiaro ed esplicativo.

Al nome seguono i parametri tra parentesi tonde.

Parametri e Argomenti

I parametri sono variabili elencate nella definizione della funzione. Gli argomenti sono i valori passati alla funzione quando viene chiamata. Esistono diversi tipi di parametri in Python, una differenza:

  1. Parametri Posizionali: i valori vengono passati ai parametri nell’ordine in cui sono definiti nella funzione.
  2. Parametri Nominali: anche detti Keyword Arguments, i valori di copia vengono passati specificando il nome del parametro. In questo modo il passaggio dei parametri può essere fatto senza l’ordine preciso scelto nella definizione della funzione. Decisamente comodo se i parametri sono molti e alcuni sono addirittura opzionali.
  3. Parametri di Default: parametri che hanno un valore di default se nessun valore viene passato.
  4. Passaggio per riferimento: i più complessi da comprendere per gli studenti. Permettono di passare un numero variabile per riferimento, cioè non un valore di copia, ma il contenuto di memoria della variabile chiamante.
  5. Parametro di ritorno: qui qualche collega salta sulla sedia probabilmente ma no, non è previsto un tipo di ritorno delle funzioni python, proprio perché non è un linguaggio tipizzato. Esiste però una una buona prassi di inserire -> int ovvero un frecciolina e il tipo di ritorno int, chr, float, bool. Non è eseguito a runtime, non è un reale controllo ma è una buona prassi per commentare meglio il proprio codice.

La sezione del def nome parametri tipodiritorno si conclude con il due punti :

Ecco un esempio che mostra l’uso di diversi tipi di parametri:

def sum(addendo1, addendo2) -> int:
    return (a + b)

a = int(input('Inserisci il primo numero: '))
b = int(input('Inserisci il secondo numero: '))


print(sum(addendo1=a, addendo2=b))
#così puoi scambiare ordine dei parametri, soprattutto se numerosi
print(sum(addendo2=b,addendo1=a))

print(f'Sum of {a} and {b} is {sum(a, b)}')

Funzioni integrate o moduli

Esistono alcune funzioni già integrate nel codice Python, senza bisogno di aggiungere codice per dichiararle. Non è facile fare un elenco perché sono in numero decisamente elevato.

print("testo a piacere")  #funzione di stampa
input("messaggio")   # variabile = input("Scrivi un saluto") 

abs(-26)   #valore assoluto
pow(2,3) #esegue la potenza di 2 alla 3, fornendo il risultato 8
min(13,45,3,12)   #valore minimo di un elenco di numeri o variabili numeriche
max(3,6,12,5,34) #valore massimo di un elenco di numeri o variabili numeriche

int(34.5)  #effettua una conversione di un numero in intero
float(100) #effettua una conversione di un numero in decimale con virgola
str(123) #converte un numero nella stringa di caratteri corrispondente

len() #da la lunghezza ovvero numero di elementi di un vettore o di una stringa
open() #per aprire in lettura/scrittura i file
split() #suddivide una stringa in base a spazi o carattere scelto
join() # il contrario di split, unisce stringhe

append() #aggiunge elementi ad un vettore
pop() #estrae un elemento da una lista vettore
sort() #ordina un vettore

Le funzioni ovviamente hanno dei parametri e delle tecniche che si suggerisce approfondire in altri articoli o guide.

Alcune funzioni non sono integrate ma possono esser aggiunte importando dei moduli, alcuni standard, altri previa installazione sul dispositivo in uso.

I moduli estendono le funzioni utilizzabili nei nostri frammenti di codice. Esistono moduli per funzionalità più disparate e per ogni contesto applicativo, dalla grafica, interfacce GUI, calcolo matematico, videogiochi, ecc Ne mostriamo solo alcuni per scopi didattici che possono tornare utili quindi agli alunni. I moduli vengono in genere installati con pacchetti specifici sui sistemi operativi Linux o con il comando pip che fa riferimento ad una serie di repository non ufficiale ma molto comoda per scaricare librerie comunque di utilità acclarata.

import math

math.sqrt(16)  #radice quadrata di un numero diretto o attraverso variabile

Funzioni lambda

Python supporta anche funzioni anonime, ovvero non specificatamente dichiarate. Sono conosciute come funzioni lambda. In genere sono funzioni particolarmente semplici scrivibili in una sola riga. specificando la parola chiave lambda.

Ecco un esempio di una funzione lambda che calcola il quadrato di un numero:

quadrato = lambda x: x ** 2
print(quadrato(4))  # Output: 16

L'articolo Le funzioni in Python proviene da alfredocentinaro.it.

]]>
Sostituisci pattern in una stringa https://www.alfredocentinaro.it/lezioni/python/python-base/sostituisci-pattern-in-una-stringa/ Wed, 06 Mar 2024 13:52:21 +0000 https://www.alfredocentinaro.it/?p=7270 Realizziamo uno script con una funzione sostituisci che prenda in input una stringa di testo, una stringa da cercare, una nuova stringa, e restituisca una stringa derivata dalla stringa originale dove tutte le occorrenze del pattern da cercare sono state sostituite dalla stringa nuova. Per esempio, nel caso stringa=”ooooo”, pattern = “oo” e nuovopattern = ... Leggi tutto

L'articolo Sostituisci pattern in una stringa proviene da alfredocentinaro.it.

]]>
Realizziamo uno script con una funzione sostituisci che prenda in input una stringa di testo, una stringa da cercare, una nuova stringa, e restituisca una stringa derivata dalla stringa originale dove tutte le occorrenze del pattern da cercare sono state sostituite dalla stringa nuova. Per esempio, nel caso stringa=”ooooo”, pattern = “oo” e nuovopattern = “ca”, la funzione deve restituire “cacao”.

Soluzione

Il problema non è esattamente banale per un alunno alle prime armi, che sia di scuola superiore che universitario. Occorrono più funzioni e accorgimenti per giungere ad un algoritmo efficace. L’idea alla base potrebbe essere:

  • ciclo cercando nella stringa il pattern
  • se esiste, individuo la posizione della lettera iniziale
  • sostituisco il nuovo pattern al vecchio

Per semplicità dividiamo le due funzionalità “esiste pattern” e “posizione pattern” con due funzioni Python. Potremmo agire con una unica funzione semplicemente “posizione pattern”. Questa infatti scorre la stringa e cerca la prima ripetizione del pattern restituendo l’indice lettera da dove comincia. Ritorna -1 se non trova nulla essendo un valore arbitrario. La funzione esiste fa la stessa cosa per certi versi ma torna vero o falso a seconda che trovi una ripetizione del pattern. Potremmo tranquillamente usare solo la prima delle due visto che comunque c’è un indicatore di ritorno che ci da o meno l’esistenza. Per completezza le inseriamo entrambe.

Vediamone una delle due. L’idea alla base è di scorrere tutta la parola/stringa iniziale. In realtà non serve scorrerla tutta perché il pattern deve essere completamente incluso nella parola quindi possiamo fermarci a cercare alla lungheza della parola meno quella del patetrn. Usiamo un indice numerico con range per procedere. A questo punto controllo le lettere del pattern se sono uguali a blocchi successivi di lettere usando un indice ulteriore che aumento manualmente mano a mano che trovo letetre uguali. Se arrivo a trovare tante lettere quante il pattern allora ho trovato un blocco di lettere uguali al pattern stesso e posso ritornare l’indice del primo ciclo che si era fermato per controllare la corrispondenza del secondo ciclo. Se il blocco controllato fallisce, resetto il conteggio delle lettere uguali e procedo alla lettera successiva nella parola controllando ancora che questa sia l’inizio o meno di un blocco pari al pattern. E così via.

def posizione(stringa, pattern):
    for i in range(0, len(stringa)-len(pattern)):
        contalettere = 0
        j = i #parto dalla lettera in cui mi trovo
        for lettera in pattern:
            if lettera == stringa[j]:
                contalettere += 1
                j += 1
        if contalettere == len(pattern):
            return i
    return -1

Codice

Il listato completo con programma main e funzioni di supporto.

def esiste(stringa, pattern):
    for i in range(0, len(stringa)-len(pattern)):
        contalettere = 0
        j = i #parto dalla lettera in cui mi trovo
        for lettera in pattern:
            if lettera == stringa[j]:
                contalettere += 1
                j += 1
        if contalettere == len(pattern):
            return True
        contalettere = 0 #da resettare ogni blocco controllato
    return False

def posizione(stringa, pattern):
    for i in range(0, len(stringa)-len(pattern)):
        contalettere = 0
        j = i #parto dalla lettera in cui mi trovo
        for lettera in pattern:
            if lettera == stringa[j]:
                contalettere += 1
                j += 1
        if contalettere == len(pattern):
            return i
        contalettere = 0 #da resettare ogni blocco controllato
    return -1


def sostituisci(stringa, nuovopattern, posizione):
    nuovaparola = ""

    #copio la parte che non va sostituita
    for i in range(0, posizione):
        nuovaparola += stringa[i]

    #inserisco il pattern nella posizione
    nuovaparola += nuovopattern

    #copio la parte rimannte della parola dopo la sostituzione
    for i in range(posizione + len(nuovopattern), len(stringa)):
        nuovaparola += stringa[i]

    return nuovaparola


if __name__ == "__main__":
    stringa = "ooooo"
    pattern = "oo"
    nuovopattern = "ca"
    #print(sostituisci("pippo", "aa",2))
    while esiste(stringa, pattern):
        pos = posizione(stringa, pattern)
        stringa = sostituisci(stringa, nuovopattern,pos)
    print(stringa)    #atteso cacao

L'articolo Sostituisci pattern in una stringa proviene da alfredocentinaro.it.

]]>
Stampa lettere di una parola con occorrenza singola https://www.alfredocentinaro.it/lezioni/python/python-base/stampa-lettere-con-occorrenza-singola/ Wed, 06 Mar 2024 07:19:59 +0000 https://www.alfredocentinaro.it/?p=7257 Proponiamo un esercizio in Python con le stringhe dove inseriamo una parola o da input o in modalità Test Driven. Vogliamo che una funzione opportuna ci restituisca una nuova parola composta dalle sole lettere che si ripetono una sola volta, ovvero hanno occorrenza uno. Ad esempio: se inserisco “pazzerello” -> stampa “paro” Soluzione L’idea alla ... Leggi tutto

L'articolo Stampa lettere di una parola con occorrenza singola proviene da alfredocentinaro.it.

]]>
Proponiamo un esercizio in Python con le stringhe dove inseriamo una parola o da input o in modalità Test Driven. Vogliamo che una funzione opportuna ci restituisca una nuova parola composta dalle sole lettere che si ripetono una sola volta, ovvero hanno occorrenza uno. Ad esempio: se inserisco “pazzerello” -> stampa “paro”

Soluzione

L’idea alla base della soluzione deve sempre utilizzare in modo sapiente i cicli per esplorare la parola assegnata. Sappiamo che Python ha almeno due modi di scorrere una parola: o utilizzare un indice numerico sfruttando il range o sfruttando la modalità elemento su vettore/insieme.

In particolare avremo bisogno di un ciclo iniziale che scorre ogni singola lettera dell’insieme/stringa. Un secondo ciclo annidato riscorre ancora tutta la parola prendendo come riferimento la lettera “in canna” del primo ciclo e conteggia con un semplice if la corrspondenza col secondo ciclo. Ogni volta che terminiamo il secondo ciclo, vado a controllre la variabile contatore. Se questa ha un numero maggiore di uno, la lettera va scartata. Altrimenti la vado ad aggiungere ad una parola da restituire a conclusione di entrambi i cicli, qui chiamata parolaoccorrenzesingole.

Codice

def occorrenzesingole(stringa):
    contatore = 0
    parolaoccorrenzesingole = ""
    for lettera in stringa:
        for letteradacontare in stringa:
            if lettera == letteradacontare:
                contatore += 1
        if contatore == 1:
            parolaoccorrenzesingole += lettera
        contatore = 0    #resetto il contatore di occorrenze        
    return parolaoccorrenzesingole

if __name__ == "__main__":
    print(occorrenzesingole("pazzerello"))   #deve stampare paro

L'articolo Stampa lettere di una parola con occorrenza singola proviene da alfredocentinaro.it.

]]>
Eliminare stringhe lunghe da file https://www.alfredocentinaro.it/lezioni/python/python-base/eliminare-stringhe-lunghe-da-file/ Fri, 16 Feb 2024 23:43:59 +0000 https://www.alfredocentinaro.it/?p=6952 Esercizio apparentemente semplice. Vogliamo leggere un file in cui sono presenti un certo numero di righe, ognuna delle quali con una sequenza di caratteri più o meno lunga. Il software deve leggere il file ed eliminare le righe più lunghe di 20 caratteri. Approccio Esistono più modi di affrontare il problema, vista anche la genericità ... Leggi tutto

L'articolo Eliminare stringhe lunghe da file proviene da alfredocentinaro.it.

]]>
Esercizio apparentemente semplice. Vogliamo leggere un file in cui sono presenti un certo numero di righe, ognuna delle quali con una sequenza di caratteri più o meno lunga. Il software deve leggere il file ed eliminare le righe più lunghe di 20 caratteri.

Approccio

Esistono più modi di affrontare il problema, vista anche la genericità della specifica. Non sappiamo infatti molto sul contenuto del testo se le righe sono con parole di senso compiuto, punteggiatura e spazi vuoti. Diamo per assodato che le stringhe siano di lettere consecutive che possiamo leggere quindi in una sola istruzione e inserirle su una una struttura dati a lista.

Una volta importata la lista, possiamo agire su di questa per trovare la stringa con il numero di caratteri non desiderato oppure fare il contrario: cerchiamo tutte le stringhe che non sono da eliminare e le inseriamo in una lista “buona”. Questa soluzione forse è più semplice da perseguire poiché potrebbe essere critico scorrere ed eliminare elementi di una lista senza incorrere in qualche problema.

Nel codice abbiamo lasciato commentati alcuni test che possiamo stampare per controllare l’andamento corretto del codice e dell’algoritmo pensato.

Altro dettaglio leggere un file tutto di un fiato con l’istruzione read() è semplice. Col comando split() si rileva il carattere vuoto di termine riga e quindi si dividono le diverse righe. Mentre per scrivere occorre aggiungere un \n che va a capo poiché il comando writelines prende una lista e la copia sul file senza spazi o andate a capo esplicite.

Per una lettura e scrittura del file o meglio una riscrittura intera, abbiamo preferito separare le operazioni di read e write per comodità logica.

'''
Leggi le righe di un file di cui inseriamo il file da console
 ed elimina quelle più lunghe di 20 caratteri
es.   aaaaaaa
      bbbbbbbbbbbbbbbb
      cccc
diventa:
      aaaaaaa
      cccc
'''

def rimuovi_lista(lista):
    lista_nuova = []
    for i in range(0, len(lista)):
        #print(lista[i], " ", len(lista[i]))
        if (len(lista[i]) < 20):
            lista_nuova.append(lista[i] + "\n")
    return lista_nuova


if __name__ == "__main__":
    nome = input("Inserisci il nome del file da aprire: ")
    file = open(nome, "r")
    lista = file.read().split()
    file.close()

    file = open(nome, "w")
    lista_modificata = rimuovi_lista(lista)
    #print(lista_modificata)
    file.writelines(lista_modificata)
    file.close()

L'articolo Eliminare stringhe lunghe da file proviene da alfredocentinaro.it.

]]>
Convertire un numero in parole https://www.alfredocentinaro.it/lezioni/python/python-base/convertire-un-numero-in-parole/ Mon, 08 Jan 2024 21:49:19 +0000 https://www.alfredocentinaro.it/?p=6726 Vogliamo inserire da tastiera un numero intero di al massimo 3 cifre e convertirlo in parole. Es 321 => trecentoventuno Utilizzare in modo ottimale funzioni per scomporre il problema. La soluzione Per prima cosa ci occorre leggere un numero da tastiera. La funzione è piuttosto semplice e l’abbiamo sicuramente vista in molti esercizi. Possiamo aggiungere ... Leggi tutto

L'articolo Convertire un numero in parole proviene da alfredocentinaro.it.

]]>
Vogliamo inserire da tastiera un numero intero di al massimo 3 cifre e convertirlo in parole. Es 321 => trecentoventuno Utilizzare in modo ottimale funzioni per scomporre il problema.

La soluzione

Per prima cosa ci occorre leggere un numero da tastiera. La funzione è piuttosto semplice e l’abbiamo sicuramente vista in molti esercizi. Possiamo aggiungere i controlli di validità che desideriamo. qui cil imitiamo a validare che il numero non sia nullo, negativo o a quattro cifre.

def leggiNumero():
    numero = -1
    while numero <= 0 or numero > 999:
        numero = int(input("Inserisci un numero:  "))

    return numero

Inserito il numero dobbiamo scomporlo per avere ognuna delle sue cifre e il loro relativo peso unità/decine/centinai. La soluzione più semplice è di usare un vettore dove inserire le cifre che reperiamo dividendo progressivamente il numero per 10, prendendo il resto e troncando la parte decimale in modo da ottenere la cifra desiderata. La possiamo quindi appendere/aggiungere ad una lista.

def scomposizione(numero):
    lista = []
    while numero > 0:
        resto = numero % 10
        numero = math.trunc(numero / 10)
        lista.append(resto)

Siamo già a buon punto. La funzione di scomposizione è quella che forse logicamente potrebbe mettere in difficoltà lo studente meno esperto. Ora si tratta di rileggere le nostre cifre nella lista e assegnargli una parola. Usiamo il costrutto match presenta solo dalla versione 3.10 di python rilasciata nel 2021. La versione è piuttosto recente quindi in alcune macchine non aggiornate potrebbe essere necessario utilizzare una soluzione alternativa con la costruzione di if/else annidati o usare strutture dati interessanti come i dizionari.

La funzione tiene conto della lunghezza della lista in modo da stampare le opportune scritte per centinaia o decine. Attenzione a combinare le parole con un operatore +=

def converti(lista):
    parola = ""

    if len(lista) <= 0:
        return

    if len(lista) == 3:
        match lista[2]:
            case 9:
                parola = "novecento"

            case  8:
                parola = "ottocento"

            #ecc...

    if len(lista) >= 2:
        match lista[1]:
            case 9:
                parola += "novanta"
            
             #ecc...

Il main è piuttosto semplice, si limita a combinare e chiamare i risultati delle funzioni appena commentate.

Listato completo

import math


def leggiNumero():
    numero = -1
    while numero < 0 or numero > 999:
        numero = int(input("Inserisci un numero:  "))

    return numero


def scomposizione(numero):
    lista = []
    while numero > 0:
        resto = numero % 10
        numero = math.trunc(numero / 10)
        lista.append(resto)

    return lista


def converti(lista):
    parola = ""

    #attendo che il numero 321 in lista sia:
    # lista[0] = 1
    # lista[1] = 2
    # lista[2] = 3

    if len(lista) <= 0:
        return

    if len(lista) == 3:
        match lista[2]:
            case 9:
                parola = "novecento"

            case  8:
                parola = "ottocento"

            case 7:
                parola = "settecento"

            case 6:
                parola = "seicento"

            case 5:
                parola = "cinquecento"

            case 4:
                parola = "quattrocento"

            case 3:
                parola = "trecento"

            case 2:
                parola = "ducento"

            case 1:
                parola = "cento"

            #case 0 non serve aggiungere nulla

    if len(lista) >= 2:
        match lista[1]:
            case 9:
                parola += "novanta"

            case 8:
                parola += "ottanta"

            case 7:
                parola += "settanta"

            case 6:
                parola += "sessanta"

            case 5:
                parola += "cinquanta"

            case 4:
                parola += "quaranta"

            case 3:
                parola += "trenta"

            case 2:
                parola += "venti"

            case 1:
                parola += "dieci"

            #case 0 non serve


    match lista[0]:
        case 9:
            parola += "nove"

        case  8:
            parola += "otto"

        case 7:
            parola += "sette"

        case 6:
            parola += "sei"

        case 5:
            parola += "cinque"

        case 4:
            parola += "quattro"

        case 3:
            parola += "tre"

        case 2:
            parola += "due"

        case 1:
            parola += "uno"

    return parola


if __name__ == "__main__":
    numero = leggiNumero()
    lista = scomposizione(numero)
    parola = converti(lista)
    print(parola)

L'articolo Convertire un numero in parole proviene da alfredocentinaro.it.

]]>
Cifrario di Cesare in C++, Rust, Python, Java https://www.alfredocentinaro.it/lezioni/java/cifrario-di-cesare-in-c-rust-python-java/ Thu, 13 Apr 2023 22:57:19 +0000 https://www.alfredocentinaro.it/?p=4679 Un esercizio decisamente classico per i novelli della programmazione. Vediamo un semplice cifrario di Cesare che funziona nel seguente modo: viene inserito un testo arbitrario, viene inserita una chiave numerica, si traspone il testo lettera per lettera di tante posizioni alfabetiche secondo la chiave e si fornisce in output il testo crittografato. Per completezza sviluppiamo ... Leggi tutto

L'articolo Cifrario di Cesare in C++, Rust, Python, Java proviene da alfredocentinaro.it.

]]>
Un esercizio decisamente classico per i novelli della programmazione. Vediamo un semplice cifrario di Cesare che funziona nel seguente modo: viene inserito un testo arbitrario, viene inserita una chiave numerica, si traspone il testo lettera per lettera di tante posizioni alfabetiche secondo la chiave e si fornisce in output il testo crittografato. Per completezza sviluppiamo una soluzione in diversi linguaggi, confrontando così le potenzialità di ognuno.

Versione C++

Presentiamo il nostro cifrario forse in modo un po’ più complesso, aggiungendo un menù per scegliere l’operazione da effettuare, se cifrare o decifrare un testo. In questo modo il main diventa semplicemente un loop per la scelta dell’operazione mentre alle due funzioni cifra/decifra è affidato il compito specifico. L’alunno che necessita dell’esercizio in modo più semplice può limitarsi al codice di una delle due funzioni cifra/decifra.

L’algoritmo di suo è piuttosto semplice. Le funzioni in realtà sono speculari: una aggiunge la chiave, l’altra lo sottrae per riottenere il testo in chiaro. L’unico dettaglio che forse è il caso notare sono le diciture:

    cin.ignore();
    getline(cin, testoInChiaro);

Le stringhe C++ infatti non ammettono gli spazi se lette da cin > qualcosa, mentre con questo stratagemma, possiamo inserire un testo dotato di lettere, numeri, punteggiatura varia e spazi!

#include <iostream>
#include <string>

using namespace std;

void cifra()
{
    string testoInChiaro;
    string testoCifrato;
    int chiave;

    cout << "Scegli la chiave (intero +/- 25 max)" ;
    do 
    {
        cin >> chiave;
    }
    while (chiave < -26 || chiave > 26);
    
    cout << "Inserisci il testo da crittografare" << endl;
    cout << ": ";
    cin.ignore();
    getline(cin, testoInChiaro);

    for (int i = 0; i < testoInChiaro.length(); i++)
    {
            testoCifrato += testoInChiaro[i] + chiave;
    } 

    cout << "Testo crittografato" << endl;
    cout << ": ";
    cout << testoCifrato << endl;
}


void decifra()
{
    string testoInChiaro;
    string testoCifrato;
    int chiave;

    cout << "Indica la chiave scelta precedentemente (intero +/- 25 max)" ;
    do 
    {
        cin >> chiave;
    }
    while (chiave < -26 || chiave > 26);
    
    cout << "Inserisci il testo da decifrare" << endl;
    cout << ": ";
    cin.ignore();
    getline(cin, testoCifrato);

    for (int i = 0; i < testoCifrato.length(); i++)
    {
            testoInChiaro += testoCifrato[i] - chiave;
    } 

    cout << "Testo in chiaro" << endl;
    cout << ": ";
    cout << testoInChiaro << endl;
}

int main()
{
    int scelta = 0;

    cout << "|-------------------------|" << endl;
    cout << "|   CIFRARIO DI CESARE    |" << endl;
    cout << "|-------------------------|" << endl;
    cout << endl;

    do 
    {
        cout << "Cosa vuoi fare? "<<endl;
        cout << "1 - Cifrare " << endl;
        cout << "2 - Decifrare " << endl;
        cout << "0 - Uscire " << endl;
        cin >> scelta;

        switch (scelta)
        {
        case 1:
            cifra();
            break;

        case 2:
            decifra();
            break;

        case 0:
            return 0;
            break;
        
        default:
            //non faccio nulla richiedo l'input
            break;
        }

    }
    while(scelta != 0);

    return 0;
}

Versione Rust

Con Rust implementiamo il medesimo algoritmo ed interfaccia del C++ ma i due linguaggi sono profondamente diversi. Per certi versi il Rust sembra avere un approccio più a basso livello del fratellone. Gli input e i cicli do-while apparentemente hanno una sintassi più complessa, idem il cast lettera/numero per l’aggiunta della chiave.

use std::io;

fn cifra()
{
    let mut testoCifrato = String::new();
    let mut chiave :i32;

    loop
    {
        println!("Scegli la chiave (intero +/- 25 max)");
        let mut input = String::new();
        io::stdin().read_line(&mut input);
        chiave = input.trim().parse().expect("Chiave non valida");
        if chiave > -26 || chiave < 26
        {
            break;
        }
    }

    println!("Inserisci il testo da crittografare");
    let mut testoInChiaro = String::new();
    io::stdin().read_line(&mut testoInChiaro);

    for i in 0..testoInChiaro.len() -1
    {
        let carattere = testoInChiaro.chars().nth(i).unwrap();
        let carattere_trasp= carattere as u8 + chiave as u8;
        testoCifrato.push(char::from(carattere_trasp));
    }

    println!("Testo crittografato");
    println!(": {}",testoCifrato);
}

fn decifra()
{
    let mut testoInChiaro = String::new();
    let mut chiave :i32;

    loop
    {
        println!("Inserisci la chiave in tuo possesso (intero +/- 25 max)");
        let mut input = String::new();
        io::stdin().read_line(&mut input);
        chiave = input.trim().parse().expect("Chiave non valida");
        if chiave > -26 || chiave < 26
        {
            break;
        }
    }

    println!("Inserisci il testo da decifare");
    let mut testoCifrato = String::new();
    io::stdin().read_line(&mut testoCifrato);

    for i in 0..testoCifrato.len() -1
    {
        let carattere = testoCifrato.chars().nth(i).unwrap();
        let carattere_trasp= carattere as u8 - chiave as u8;
        testoInChiaro.push(char::from(carattere_trasp));
    }

    println!("Testo decifrato");
    println!(": {}",testoInChiaro);
}

fn main()
{
    println!("|-------------------------|");
    println!("|   CIFRARIO DI CESARE    |");
    println!("|-------------------------|");
    println!();

    let mut scelta = 0;

    loop
    {
        println!("Cosa vuoi fare? ");
        println!("1 - Cifrare ");
        println!("2 - Decifrare ");
        println!("0 - Uscire ");

        let mut input = String::new();
        io::stdin().read_line(&mut input);
        scelta = input.trim().parse()
            .expect("Non hai inserito un numero valido");

        match scelta
        {
            1=>cifra(),
            2=>decifra(),
            0=>return,
            _=>println!("Scelta non valida"),
        }

        if scelta == 0 { break; }
    }
}

Versione Python

La versione Python del medesimo algoritmo ha implementazione molto semplice, forse di gran lunga più semplice di C++ e Rust.


def cifra():
    while True:
        chiave=eval(input("Inserisci la chiave (intero +/- 25 max): "))
        if chiave >= -26 and chiave <= 26:
            break
    testoInChiaro = input("Inserisci il testo da crittografare")
    testoCifrato = ""
    for lettera in testoInChiaro:
        testoCifrato += chr(ord(lettera)+chiave)
    
    print("Testo cifrato")
    print(": ", testoCifrato)

def decifra():  
    while True:
        chiave=eval(input("Inserisci la chiave (intero +/- 25 max): "))
        if chiave >= -26 and chiave <= 26:
            break

    testoCifrato = input("Inserisci il testo da crittografare")
    testoInChiaro = ""
    for lettera in testoCifrato:
        testoInChiaro += chr(ord(lettera)-chiave)
            
    print("Testo decifrato")
    print(": ",testoInChiaro)

    
if __name__ == "__main__":
    print("|-------------------------|\n")
    print("|   CIFRARIO DI CESARE    |\n")
    print("|-------------------------|\n")

    while True:
        print("Cosa vuoi fare? ")
        print("1 - Cifrare ")
        print("2 - Decifrare ")
        print("0 - Uscire ")
        scelta= eval(input())
        
        match scelta:
            case 1:
                cifra()
            case 2:
                decifra()
            case 0:
                exit()
            case _:
                print("Errore")
        

Versione Java

TO DO

import java.util.Scanner;

public class Cifrario
{
    public static void cifra()
    {
        int chiave;
        String testoCifrato = new String();
        do {
            System.out.println("Inserisci la chiave in tuo possesso (intero +/- 25 max)");
            Scanner s = new Scanner(System.in);
            chiave = s.nextInt();
        }
        while (chiave < -26 || chiave > 26);

        System.out.println("Inserisci il testo da crittografare");
        Scanner s = new Scanner(System.in);
        String testo = s.nextLine();

        for (int i = 0; i < testo.length(); i++)
        {
            char lettera = testo.charAt(i);
            //testoCifrato += lettera + (char)chiave; NO usa vettore di char e poi riconverti in new String
        }

        System.out.println(testoCifrato);
    }

    public static void decifra()
    {

    }

    public static void main(String [] args)
    {
        System.out.println("|-------------------------|");
        System.out.println("|   CIFRARIO DI CESARE    |");
        System.out.println("|-------------------------|");
        System.out.println();
        int scelta;

        while (true)
        {
            System.out.println("Cosa vuoi fare? ");
            System.out.println("1 - Cifrare ");
            System.out.println("2 - Decifrare ");
            System.out.println("0 - Uscire ");

            do
            {
                Scanner s = new Scanner(System.in);
                scelta = s.nextInt();
            }
            while(scelta < 0 && scelta > 2);

            switch (scelta)
            {
                case 1:
                    cifra();
                    break;

                case 2:
                    decifra();
                    break;

                case 0:
                    return;
            }

        }

    }
}

L'articolo Cifrario di Cesare in C++, Rust, Python, Java proviene da alfredocentinaro.it.

]]>
Le classi in Python https://www.alfredocentinaro.it/lezioni/python/python-base/le-classi-in-python/ Fri, 26 Aug 2022 09:38:53 +0000 https://www.alfredocentinaro.it/?p=2901 Partiamo dal presupposto che il lettore conosca già un po’ di teoria della programmazione ad oggetti. In questo articolo vogliamo riassumere gli elementi pratici per realizzare una classe in Python. Partiamo dal presupposto che il python, non essendo un linguaggio compilato, ha una sintassi per la gestione delle classi più poliedrica rispetto ai fratelli più ... Leggi tutto

L'articolo Le classi in Python proviene da alfredocentinaro.it.

]]>
Partiamo dal presupposto che il lettore conosca già un po’ di teoria della programmazione ad oggetti. In questo articolo vogliamo riassumere gli elementi pratici per realizzare una classe in Python.

Partiamo dal presupposto che il python, non essendo un linguaggio compilato, ha una sintassi per la gestione delle classi più poliedrica rispetto ai fratelli più blasonati C++ o Java o C#, solitamente preferiti come linguaggi per un approccio alla Programmazione Orientata agli Oggetti (OOP).

E già con questo mini esempio iniziale dovrebbe essere palese. Creiamo un file Studente.py con il seguente listato:

class Studente:
    nome= "Alfredo"

if __name__ == "__main__":
    s = Studente()
    print(s.nome)

Eseguiamo da terminale nella posizione di salvataggio con il comando python Studente.py o eseguiamolo da IDLE.

Possiamo già notare delle anomalie: nella classe non abbiamo creato un costruttore ma abbiamo inserito una variabile che funge da classico attributo, inizializzata per giunta nello stesso contesto senza una dicitura di pubblico o privato. Nel programma principale abbiamo creato una istanza e abbiamo stampato con accesso diretto il valore dell’attributo della classe. In questo modo è decisamente più veloce e semplice realizzare le classi, la sintassi è ridotta davvero all’osso.

Proviamo a rendere la nostre classi più simili agli standard OOP e aggiungiamo un metodo di stampa e un costruttore.

class Studente:
    def __init__(self, _nome, _cognome):
        self.nome = _nome
        self.cognome = _cognome
        self.annonascita = 1700

    def print(self):
        print("Nome: " + self.nome + "\n" + "Cognome: " + self.cognome + "\n" + "Anno di nascita: "+self.annonascita )

if __name__ == "__main__":
    s = Studente("Alfredo", "Centinaro")
    s.annonascita = 1982
    s.print()

Come possiamo vedere, abbiamo una similitudine tra il classico elemento this che qui in python diventa self. Si usa anche come primo parametro, o meglio una sorta di pseudo parametro nei metodi per permettere l’invocazione sull’istanza della classe stessa.

Il costruttore qui non ha il nome della classe, ma __init__ e prende i parametri che si vuole passare al costruttore per inizializzare l’oggetto. Perché utilizzare il costruttore se posso direttamente inizializzare le variabili? In realtà è una questione di praticità. Le variabili dentro l’__init__ assumo il valore specifico solo per l’istanza che chiama il costruttore. Le variabili fuori dall’__init__, vengono dette variabili di classe e hanno lo stesso valore per tutte le istanze a prescindere, un po’ come se fossero valori statici, almeno inizialmente. Non conviene usare variabili sparse se vogliamo essere puntigliosi del mondo OOP. Se all’interno dell’istanza modifico il valore della variabile di classe, questa modifica solo la singola istanza pero!

class Studente:

    annodicorso = 1

    def __init__(self, _nome, _cognome):
        self.nome = _nome
        self.cognome = _cognome
        self.annonascita = 1700
    def print(self):
        print("Nome: " + self.nome + "\n" + 
              "Cognome: " + self.cognome + "\n" + 
              "Anno di nascita: "+ str(self.annonascita) + "\n" +
              "Anno di corso: " + str(self.annodicorso) )

if __name__ == "__main__":
    s = Studente("Alfredo", "Centinaro")
    s.annonascita = 1982
    s.print()

    z = Studente("Pippo", "Franco")
    z.annonascita = 1973
    z.annodicorso = 2
    z.print()    

Se lanciamo il codice di questa versione di classe otteniamo:

Nome: Alfredo
Cognome: Centinaro
Anno di nascita: 1982
Anno di corso: 1
Nome: Pippo
Cognome: Franco
Anno di nascita: 1973
Anno di corso: 2

Continua però a non esserci un sistema di protezione ed incapsulamento: possiamo alterare il nostro oggetto in modo diretto anche senza specificare un metodo di accesso o modifica, che diventano quindi quasi inutili. L’evidenza qui è nell’attributo annonascita che viene modificato direttamente prima della stampa.

Vedremo nelle prossime lezioni scope, namespace ed ereditarietà.

L'articolo Le classi in Python proviene da alfredocentinaro.it.

]]>