Profilo di RicPol

Nome RicPol
Indirizzo email ric.pol@libero.it
AvatarAvatar utenti
Messaggi127
Firma forum
https://pythoninwindows.blogspot.com/p/blog-page.html
Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: modulo abc
    Forum >> Principianti
    Questo è python avanzato, molto avanzato. Ed è OOP avanzata. La risposta breve è quella di Tim Peters che si dà di solito per le metaclassi in generale, al punto che è diventata proverbiale: se non sai a che cosa servono le metaclassi, vuol dire che non ne hai bisogno. Il tuo esempio è un caso tipico: per cose così semplici va benissimo come fai tu, senza bisogno di scomodare le abc.


    La risposta più completa è qui https://www.python.org/dev/peps/pep-3119/#rationale scritta da Guido stesso. Detto in brevissimo, una abc, inserita in un punto precedente della gerarchia, è un "contratto" che garantisce che un test fatto con isinstance su una sottoclasse riuscirà, e che quindi la sottoclasse avrà certe proprietà definite nel contratto. Questo ha senso quando si vogliono testare le proprietà di una (sotto)classe invece che invocare le proprietà che si sa che esistono... e quando queste tecniche di ispezione possono aver senso? Eh, questa è OOP avanzata, appunto.


    Le metaclassi e le abc in particolare sono nel loro ambiente naturale quando uno costruisce una gerarchia di classi relativamente estesa, e soprattutto estendibile da terze parte oltre il progetto dell'autore originale, e/o dove è previsto che l'ispezione sarà una tecnica comune per il codice cliente. Esempio classico, una gerarchia di tipi. E in effetti le abc sono pesantemente usate per i tipi python, vedi modulo "collections".


    Se tutto questo non ha nessun senso per te... è perfettamente naturale e francamente non dovresti preoccupartene troppo, secondo Tim Peters.

    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: come tornare ad una stringa precedente?
    Forum >> Principianti
    Scusate, avrei una curiosità se posso: su quale libro sta studiando l'OP? Perché non immagino un libro in cui queste cose non siano spiegate.
    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: Python e Geocoding
    Forum >> Principianti
    (Posso dirlo? Resto sempre un po' stranito quando vedo queste domande "è possibile fare X con Python?". Ma c'è qualche leggenda metropolitana in giro per cui Python non sarebbe Turing-complete?)
    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: Matrici 2d e rettangoli
    Forum >> Principianti
    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: Cicli
    Forum >> Principianti
    > L'idea è di passare una serie di numeri (da 1 a 100, per esempio),
    > passarli alla funzione, farli analizzare
    > ed avere come output solo
    quelli che soddisfano il teorema

    E mi sembra una buona idea. La soluzione è

    1) scrivere il tuo "teorema" sotto forma di una funzione che accetta un numero in ingresso e restituisce True (se il test passa per quel numero) o False

    2) avere una lista di numeri da testare

    3) con un ciclo for passare ciascun numero alla funzione-teorema, e immagazzinare quelli che passano in una nuova lista.


    Quindi, per esempio:

    >>> def minore_di_venti(x):  # il "teorema" (testa se x e' minore di venti)
            if x<20: 
                return True
            return False
    
    >>> numeri = list(range(50))
    >>> numeri_buoni = []
    >>> for numero in numeri:
            if minore_di_venti(numero):
                numeri_buoni.append(numero)
    
    

    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: Inizializzazione classe
    Forum >> Principianti
    > Una classe con costruttore __init__ viene inizializzata quando si invoca o all’esecuzione dello script?


    Uhm. Daniele ti ha dato le coordinate, ma non ho capito se questa domanda è profonda oppure è solo una coincidenza dovuta all'uso scorretto dei termini...

    Allora, la risposta "da principianti" è che una classe NON viene inizializzata. E' un OGGETTO che viene inizializzato, non la classe. E l'oggetto viene inizializzato al momento della sua creazione. E per inizializzare l'oggetto Python esegue il codice contenuto nel metodo __init__, come detto da Daniele. (Nota tecnica: "creazione" e "inizializzazione" non sono sinonimi, eh? Prima l'oggetto viene creato, poi viene inizializzato. Il metodo __init__ non viene eseguito al momento della creazione dell'oggetto, ma al momento della sua inizializzazione. Ma dal punto di vista dell'utente "principiante" questa distinzione può essere ignorata).


    Il punto in cui, invece, mi era venuto un dubbio, è questo: stai forse chiedendo se il codice del metodo __init__ viene valutato a runtime o a import time? Questa sarebbe una domanda più complessa, ma appunto forse non era questo che volevi dire. Il punto qui è che ci sono dei pezzi di codice che Python valuta "subito" (a import time, come si dice, ovvero quando il modulo viene importato o eseguito), e dei pezzi di codice che Python valuta "dopo" (a runtime, ovvero solo quando vengono esplicitamente chiesti da altro codice). I metodi di istanza (e quindi anche il metodo __init__) è valutato a runtime, quindi il codice che ci metti dentro viene eseguito solo quando effettivamente crei l'oggetto. Attenzione però che per esempio i metodi di classe sono valutati a import time, ovvero il codice che ci metti è eseguito quando importi il modulo che contiene la classe.


    Se tutto questo per te non ha nessun senso, allora come non detto. Basta la risposta di Daniele.

    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: def. Un problema assurdo
    Forum >> Principianti
    Beh, capisci che se copi e incolli il codice in un post, come sappiamo che l'hai incollato giusto? Soprattutto se non lo formatti con il pulsante "code" (quello con gli "<>" nella barra dei pulsanti).


    Comunque, l'errore è evidente: la riga 2 non è rientrata correttamente. Basta verificare. Probabilmente c'è uno spazio spurio prima di "def", o qualche altro carattere nascosto che ti trascini dietro nel copia e incolla.

    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: Problema python in algoritmica
    Forum >> Principianti
    1. Esatto.La risposta è: solo la meccanica di questo algoritmo specifico garantisce che si finirà per uscire, ma non c'è nulla, in generale, che garantisca che una ricorsione prima o poi finisca. Quando si progetta una funzione ricorsiva è anzi facilissimo cascare in ricorsioni infinite. A lato pratico, in questi casi Python si accorge del problema ed emette un errore prima che il computer fonda. Però occorre prestare molta attenzione alla robustezza dell'algoritmo, prima di trasformarlo in codice vero e proprio.

    2. Proprio così. E questo insegna che anche ingegnerizzare la "via di uscita" dalla ricorsione richiede qualche attenzione architetturale. Non basta dire "ok, quando si verifica questa condizione esco". E' come un giocoliere con le palle: puoi continuare ad aggiungere palle, finché restano in aria. Ma a un certo punto l'esercizio finisce e devi fare attenzione che tutte le palle che tenevi in aria finiscano esattamente nel cestino ai tuoi piedi, nell'ordine giusto.


    3. L'idea di calcolare la lunghezza della stringa non funziona perché in nessun momento la stringa binaria è esplicitamente collegata a una variabile che puoi raggiungere. Ti ricordo che "n" non è la stringa binaria, ma il numero decimale di partenza. Se tu testi per str(n)==1, allora la tua funzione esce subito anche quando chiami binario(7), per dire. Ovviamente puoi cercare il modo per tenere traccia della stringa binaria a ogni passaggio... Ma direi che invece la strada con il contatore è più saggia... però devi implementare questo contatore... provaci... e se ci pensi su vedrai che in effetti un contatore è perfino eccessivo... in realtà basta un flag... ma prova a pensarci per conto tuo.



    --- Ultima modifica di RicPol in data 2018-11-21 18:35:27 ---
    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: Problema python in algoritmica
    Forum >> Principianti
    Eh, diciamo che non hai capito la cosa fondamentale. Mettiamola così: a ogni iterazione, quella funzione restituisce un "coso" nella forma:

    R + S

    dove "S" è una stringa, e "R" è il risultato di un'altra ricorsione. Quindi, dopo un po' di volte che ripeti la ricorsione, hai un "coso" di questo tipo:

    (((((...) + S) + S) + S) + S)

    dove "..." rappresenta il livello di ricorsione che hai raggiunto attualmente. Arrivati all'ultima ricorsione, la funzione restituisce una stringa vuota e si ferma (cioè non chiama più se stessa). Quindi, dopo l'ultima ricorsione, tu avrai un "coso" finale di questo tipo:

    (((((("") + S) + S) + S) + S) + S)

    che è ovviamente la somma di varie stringhe, ossia una stringa. In altre parole, la stringa finale è il risultato dell'accumulo progressivo delle "stringhe-resto" prodotte a ogni successiva ricorsione, più l'ultima stringa vuota di chiusura. (Le "stringhe-resto", come spero avrai capito, sono i resti convertiti in stringa: questo algoritmo mappa la procedura che faresti con carta e penna per convertire un intero decimale in binario).





    Esercizio numero 1: che cosa garantisce che a un certo punto la funzione "esca", e non continui a ricorrere all'infinito? Ovvero, che cosa garantisce che si arrivi sempre, a un certo punto, allo zero e quindi a chiamare "binario(0)"?

    Esercizio numero 2: che cosa succede se, arrivati a zero, la funzione non esce restituendo la stringa vuota, ma qualsiasi altra cosa? Cioè, per esempio, se scrivo:
    def binario(n):
        if n==0:
            return None # o "return 42", o "return False", qualunque cosa
        etc etc etc come sopra
    
    La funzione "funziona" ancora? E perché?

    Esercizio numero 3: scritta in questo modo la funzione ha un piccolo baco: se chiami "binario(0)" il risultato è una stringa vuota, cosa ovviamente sbagliata. Il binario di 0 invece è "0", ovviamente. Il problema è che quando la funzione testa "if n==0" non riesce a distinguere se sta parlando proprio del numero originale oppure del numero che riceve a una ricorsione successiva. Cioè non riesce a distinguere se in quel momento sta eseguendo la prima ricorsione, o è già arrivata a una ricorsione successiva. Bisognerebbe correggere la funzione con qualcosa del genere:
    # pseudo-codice
    def binario(n):
        if n==0 and siamo-alla-prima-ricorsione:
            return "0"
        if n==0 and siamo-oltre-la-prima-ricorsione:
            return ""
        etc etc come sopra
    
    C'è un modo per fare questo? (questo esercizio è un po' più difficile. Forse puoi usarlo per fare l'ingenuo e trollare il tuo prof. C'è una discreta possibilità che così su due piedi non lo sappia fare neanche lui).





    Detto questo, il tuo problema resta lo stesso: posso guidarti per mano, centimetro dopo centimetro; posso farti un milione di esempi e di metafore; ma se non ci ragioni sopra con la tua testa, perderndoci una giornata (ma una giornata seria, intendo: col telefonino spento, senza distrazioni, senza musica... come si faceva una volta) non ci riuscirai mai. E' proprio qualcosa che ti scatta nella testa, e deve scattarti perché riesci a visualizzarlo alla tua maniera. Poi prova con gli esercizi che ti ho proposto, poi prova altre funzioni ricorsive, eccetera.


    La ricorsione non è difficile di per sé: tuttavia è oggettivamente difficile visualizzare il flusso del programma ricorsivo nella testa. C'è solo da mettersi lì con pazienza e carta e penna.
















    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua
  • Re: Problema python in algoritmica
    Forum >> Principianti
    Non ci sono molte soluzioni per capire la ricorsione: bisogna mettersi lì con carta e penna e fare il conto, e poi rifarlo e rifarlo ancora finché non capisci come funziona. Per prima cosa, riscriviamo la funzione formattandola con l'apposito pulsante "code" (quello con il simbolo "<>") in modo che si capisca di che cosa parliamo:

    def binario(n):
        if n==0:
            return ''
        return binario(n//2) + str(n%2)
    
    Ora, è chiaro che se ti metti con carta e penna a calcolare "binario(353646545521)" non ne esci vivo. Però carta e penna è l'unico modo, fidati. Proviamo insieme a calcolare cosa succede quando scrivi


    binario(5)  # dà "101", ovviamente
    Allora, sei pronto? Via:


    PRIMO PASSAGGIO: "binario(5)"
    - 5 è uguale a 0? No, andiamo avanti
    - 5%2 è uguale a 1. Quindi la stringa finale terminerà per "1"
    - 5//2 è uguale a 2. Quindi dobbiamo calcolare binario(2)
    - stato attuale: la stringa è "....1", e dobbiamo calcolare binario(2)

    SECONDO PASSAGGIO: "binario(2)"
    - 2 è uguale a 0? No, andiamo avanti
    - 2%2 è uguale a 0. Quindi aggiungiamo a sinistra uno "0" alla stringa finale
    - 2//2 è uguale a 1. Quindi dobbiamo calcolare binario(1)
    - stato attuale: la stringa è "...01", e dobbiamo calcolare binario(1)

    TERZO PASSAGGIO: "binario(1)"
    - 1 è uguale a 0? No, andiamo avanti
    - 1%2 è uguale a 1. Quindi aggiungiamo a sinistra un "1" alla stringa finale
    - 1//2 è uguale a 0. Quindi dobbiamo calcolare binario(0)
    - stato attuale: la stringa è "...101", e dobbiamo calcolare binario(0)

    QUARTO PASSAGGIO: "binario(0)"
    - 0 è uguale a 0? Sì, quindi aggiungiamo una stringa vuota ("") a sinistra alla stringa finale, e usciamo
    - stato attuale: la stringa è "101", e non dobbiamo calcolare più nessuna ricorsione.

    Risultato: "101"

    Se non sei riuscito a seguire questi passaggi, ripetili con carta e penna finché non ci riesci. Se ci sei riuscito, prova almeno altre cinque volte con carta e penna a fare altri calcoli semplici (binario(3), binario(7), binario(9)...) finché non hai interiorizzato come funziona. Purtroppo la ricorsione funziona così, devi trovare il modo di immaginarti nella testa lo stack delle chiamate successive e i risultati parziali.




    --- Ultima modifica di RicPol in data 2018-11-20 21:49:07 ---
    https://pythoninwindows.blogspot.com/p/blog-page.html
    Le mie guide: Come installare e usare Python su Windows - Progetti Python multilingua