View Full Version : [Python] Pensare da informatico: i miei (e i vostri dubbi)
Grazie agli insegnamenti di cesare direi che sto usando più carta e penna che non il pc :D
Sono strumenti molto sottovalutati. Dovresti usarli più spesso :)
Quindi anche se la somma è prima del return non viene eseguita finchè non viene ritornato un valore? E' banale la cosa lo so, però è per capire perchè togliendo anche il primo return soltanto mi dà quell'errore
Esatto, questa è una funzione ricorsiva che dipende da se stessa per terminare il calcolo. Il primo return è il più importante perché è quello che termina la ricorsione ed incomincia il calcolo vero e proprio.
Guardando il capitolo, c’è un bel grafico già bello pronto della funzione Fibonacci con tutti i frame. Il punto che non mi è chiaro è che se chiamo Fibonacci con 4 succede che Fibonacci (3) + Fibonacci (2) fa 5. E già io qua mi fermerei, invece il diagramma va avanti e chiama Fibonacci sia con 3 che con 2 e va avanti fino a quando arriva n = 0. Fibonacci in pratica si richiama n volte fin quando non arriva a 0? E il risultato come lo calcola con tutte queste iterazioni? Mi ha un po’ confuso sta cosa, perché poi alla fine aumentando i numeri c’è sempre più “casino” nel calcolo.
Non farti ingannare dal fatto che per 4 il risultato coincida proprio con la somma dei due argomenti Fibonacci(3) + Fibonacci(2). Devi continuare finche non arrivi alla condizione di terminazione come mostrato nel grafico.
Vincenzo1968
05-11-2008, 17:57
Occhio che la ricorsione, nel caso di Fibonacci, non è indicata: e dal punto di vista della complessità computazionale e da quello dell'utilizzo della memoria.
Molto meglio utilizzare un algoritmo non ricorsivo:
def Fibonacci (n):
a = 1
b = 1
Temp = 3
Somma = 0
while Temp <= n:
Somma = a + b
a = b
b = Somma
Temp += 1
return Somma
print Fibonacci(10)
;)
~FullSyst3m~
05-11-2008, 18:10
Sono strumenti molto sottovalutati. Dovresti usarli più spesso :)
Li uso li uso ;) oltretutto essendo in ufficio e per evitare sgamo dal mio principale scrivo sull'agendina :D
Esatto, questa è una funzione ricorsiva che dipende da se stessa per terminare il calcolo. Il primo return è il più importante perché è quello che termina la ricorsione ed incomincia il calcolo vero e proprio.
Il primo return? Scusa, il primo return fa uscire dalla funzione se n è una chiave di Precedenti. Comunque non ho capito bene sta cosa se devo essere sincero, sarà perchè dovrei capire bene l'algoritmo di Fibonacci
Non farti ingannare dal fatto che per 4 il risultato coincida proprio con la somma dei due argomenti Fibonacci(3) + Fibonacci(2). Devi continuare finche non arrivi alla condizione di terminazione come mostrato nel grafico.
Il punto è proprio questo, che non capisco i calcoli che esegue prima di arrivare allo stato base. Cioè, li capisco, però sono "confusionati" e non mi sono molto chiari
Occhio che la ricorsione, nel caso di Fibonacci, non è indicata: e dal punto di vista della complessità computazionale e da quello dell'utilizzo della memoria.
Molto meglio utilizzare un algoritmo non ricorsivo:
E' stato scritto cosi per fare un esempio di come possono essere usati i dizionari. Comunque il tuo codice, non capisco perchè temp = 3. Inoltre con il tuo codice Fibonacci (10) dà 55 mentre con quello che ho postato io dà 89 :asd: Ci credo che poi non ci capisco nulla... ora comunque vado a guardare su wikipedia e mi metto a ragionare sul "problema"
Occhio che la ricorsione, nel caso di Fibonacci, non è indicata: e dal punto di vista della complessità computazionale e da quello dell'utilizzo della memoria.
P.S: ho finito di studiare il capitolo 10 e devo dire che è molto interessante. Però alcune cose non mi sono chiare, molto probabilmente sia perchè il libro in alcuni punti è abbastanza generico. sia perchè la versione di Python trattata è vecchissima, la 1.x.x e alcune cose come i long int sono calcolati in automatico. Ecco le cose che non mi quadrano molto bene:
1) Il metodo get non funziona solo con le tuple vero? Perchè nel codice del capitolo poi più avanti c'è un ConteggioLettera.get (Lettera, 0) + 1
2) Paragrafo 10.7, ConteggioLettere.sort() non funziona, mi restituisce errore
, causato dal .sort
Ecco quanto :D
~FullSyst3m~
05-11-2008, 20:15
Comunque VICIUS anche se adesso mi interessa capire le cose che ho scritto sopra, riquoto una mia frase riguardo il capitolo 9, cosi dopo che mi tolgo questi dubbi torno un attimo indietro.
Tornando al discorso di VICIUS, dovrei incapsulare la funzione ListaCasuale nel codice (trasformato in funzione) del paragrafo 9.8 in pratica?
Vincenzo1968
05-11-2008, 20:33
..
E' stato scritto cosi per fare un esempio di come possono essere usati i dizionari. Comunque il tuo codice, non capisco perchè temp = 3. Inoltre con il tuo codice Fibonacci (10) dà 55 mentre con quello che ho postato io dà 89 :asd: Ci credo che poi non ci capisco nulla... ora comunque vado a guardare su wikipedia e mi metto a ragionare sul "problema"
...
Ecco quanto :D
Intanto c'è un piccolo bug nella versione che ho postato prima. Per valori di n < 3 restituiva un risultato errato. Questa è la versione corretta:
def Fibonacci (n):
if n < 1:
print "Che cacchio fai? n dev'essere >= 1."
return 0
if n <= 2:
return 1
a = 1
b = 1
Temp = 3
Somma = 0
while Temp <= n:
Somma = a + b
a = b
b = Somma
Temp += 1
return Somma
print Fibonacci(1000)
Ho utilizzato la convenzione di cui si parla su wikipedia (http://it.wikipedia.org/wiki/Successione_di_Fibonacci), e cioè, considerare 1 come primo termine della successione; ecco perché, per il decimo numero di Fibonacci, la funzione restituisce 55.
Occhio: con la versione ricorsiva, se voglio calcolare il millesimo numero di Fibonacci, ecco cosa succede sulla mia macchina:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciRecursive.jpg
Come vedi, per grandi valori di n, la ricorsione comporta uno sconfinamento dello stack di sistema e il programma va in tilt.
Con la versione iterativa, invece, il calcolo viene tranquillamente svolto:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciNonRecursive.jpg
;)
~FullSyst3m~
05-11-2008, 20:39
Intanto c'è un piccolo bug nella versione che ho postato prima. Per valori di n < 3 restituiva un risultato errato. Questa è la versione corretta:
def Fibonacci (n):
if n < 1:
print "Che cacchio fai? n dev'essere >= 1."
return 0
if n <= 2:
return 1
a = 1
b = 1
Temp = 3
Somma = 0
while Temp <= n:
Somma = a + b
a = b
b = Somma
Temp += 1
return Somma
print Fibonacci(1000)
Ho utilizzato la convenzione di cui si parla su wikipedia (http://it.wikipedia.org/wiki/Successione_di_Fibonacci), e cioè, considerare 1 come primo termine della successione; ecco perché, per il decimo numero di Fibonacci, la funzione restituisce 55.
Occhio: con la versione ricorsiva, se voglio calcolare il millesimo numero di Fibonacci, ecco cosa succede sulla mia macchina:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciRecursive.jpg
Come vedi, per grandi valori, di n, la ricorsione comporta uno sconfinamento dello stack di sistema e il programma va in tilt.
Con la versione iterativa, invece, il calcolo viene tranquillamente svolto:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciNonRecursive.jpg
;)
Perchè quel temp = 3. Comunque io ho provato a chiamarlo anche con 1100 l'iterativa e non mi sconfina, me lo calcola tranquillamente. Ho Python 2.6
Vincenzo1968
05-11-2008, 20:47
Perchè quel temp = 3. Comunque io ho provato a chiamarlo anche con 1100 l'iterativa e non mi sconfina, me lo calcola tranquillamente. Ho Python 2.6
temp = 3 perchè, la successione di Fibonacci(considerando 1 e non 0 come primo termine), è la seguente:
1 1 2 3 5 8 13 21 34 55 89 144 etc.
per i primi due termini( n = 1 o n = 2 ), la funzione restituisce il risultato con queste righe di codice:
if n < 1:
print "Che cacchio fai? n dev'essere >= 1."
return 0
if n <= 2:
return 1
...
per n > 2 invece, calcoliamo il risultato con il ciclo while.
La versione iterativa è quella che ho postato io. La tua è ricorsiva. Prova con un valore di n = 1000000.
P.S. Prova anche, per n = 1000000 a prendere i tempi delle due versioni. Quella iterativa dovrebbe risultare più veloce ;)
cdimauro
05-11-2008, 21:08
Scusa, ma Verso non è il parametro/argomento?
Verso è la stringa da "splittare" e dev'essere sempre fornita ovviamente, mentre il parametro che rappresenta la stringa da usare per la suddivisione è opzionale, appunto.
Comunque imparate queste funzioni lascia perdere il modulo string: tutti i metodi che hai usato adesso sono disponibili direttamente nelle stringhe:
'Qui, Quo, Qua'.split(', ')
;)
Occhio che la ricorsione, nel caso di Fibonacci, non è indicata: e dal punto di vista della complessità computazionale e da quello dell'utilizzo della memoria.
Molto meglio utilizzare un algoritmo non ricorsivo:
def Fibonacci (n):
a = 1
b = 1
Temp = 3
Somma = 0
while Temp <= n:
Somma = a + b
a = b
b = Somma
Temp += 1
return Somma
print Fibonacci(10)
;)
L'obiettivo non era l'efficienza, ma imparare a lavorare con alcuni costrutti sintattici e oggetti.
In ogni caso, finché non diventa rilevante, l'efficienza si può benissimo mettere da parte. :O
Li uso li uso ;) oltretutto essendo in ufficio e per evitare sgamo dal mio principale scrivo sull'agendina :D
Il primo return? Scusa, il primo return fa uscire dalla funzione se n è una chiave di Precedenti. Comunque non ho capito bene sta cosa se devo essere sincero, sarà perchè dovrei capire bene l'algoritmo di Fibonacci
Il punto è proprio questo, che non capisco i calcoli che esegue prima di arrivare allo stato base. Cioè, li capisco, però sono "confusionati" e non mi sono molto chiari
Simula con carta e penna come ti ho detto di fare in passato, e vedrai che riuscirai a capire il meccanismo della ricorsione.
P.S: ho finito di studiare il capitolo 10 e devo dire che è molto interessante. Però alcune cose non mi sono chiare, molto probabilmente sia perchè il libro in alcuni punti è abbastanza generico. sia perchè la versione di Python trattata è vecchissima, la 1.x.x e alcune cose come i long int sono calcolati in automatico.
In effetti è una versione molto vecchia di Python. Ormai gli int vengono automaticamente passati a long, e con la versione 3.0 si "fonderanno": gli interi saranno sempre "lunghi".
Ecco le cose che non mi quadrano molto bene:
1) Il metodo get non funziona solo con le tuple vero? Perchè nel codice del capitolo poi più avanti c'è un ConteggioLettera.get (Lettera, 0) + 1
Get funziona solo coi dizionari (a meno che non ci siano altre classi che lo implementino perché ha senso, ma al momento non me ne viene in mente nessuna).
Se a get passi un altro parametro, nel caso in cui la chiave cercata non viene trovata viene restituito il parametro passato anziché sollevare un'eccezione.
2) Paragrafo 10.7, ConteggioLettere.sort() non funziona, mi restituisce errore
, causato dal .sort
Ecco quanto :D
>>> ConteggioLettere = {}
>>> for Lettera in "Mississippi":
... ConteggioLettere [Lettera] = ConteggioLettere.get \
... (Lettera, 0) + 1
...
>>> ConteggioLettere
{'i': 4, 'p': 2, 's': 4, 'M': 1}
>>> ConteggioLettere = ConteggioLettere.items()
>>> ConteggioLettere.sort()
>>> print ConteggioLettere
[('M', 1), ('i', 4), ('p', 2), ('s', 4)]
;)
Vincenzo1968
05-11-2008, 21:24
...
L'obiettivo non era l'efficienza, ma imparare a lavorare con alcuni costrutti sintattici e oggetti.
In ogni caso, finché non diventa rilevante, l'efficienza si può benissimo mettere da parte. :O
...
Per me, pensare da informatico = pensare in termini di efficienza.
Follia pura, dunque, non abituarsi a ragionare in tal senso fin dagli inizi :O
:D
~FullSyst3m~
05-11-2008, 21:49
Verso è la stringa da "splittare" e dev'essere sempre fornita ovviamente, mentre il parametro che rappresenta la stringa da usare per la suddivisione è opzionale, appunto.
Comunque imparate queste funzioni lascia perdere il modulo string: tutti i metodi che hai usato adesso sono disponibili direttamente nelle stringhe:
'Qui, Quo, Qua'.split(', ')
Un esempio del parametro del quale parli si può avere? Comunque questo significa che basta che uso l'oggetto con la notazione punto e la funzione che mi serve senza importare il modulo string?
Simula con carta e penna come ti ho detto di fare in passato, e vedrai che riuscirai a capire il meccanismo della ricorsione.
Ascolto i tuoi consigli, la uso sempre la carta e la penna, però non mi tornano alcune cose..
In effetti è una versione molto vecchia di Python. Ormai gli int vengono automaticamente passati a long, e con la versione 3.0 si "fonderanno": gli interi saranno sempre "lunghi".
Infatti, dico questo...
Get funziona solo coi dizionari (a meno che non ci siano altre classi che lo implementino perché ha senso, ma al momento non me ne viene in mente nessuna).
Se a get passi un altro parametro, nel caso in cui la chiave cercata non viene trovata viene restituito il parametro passato anziché sollevare un'eccezione.
A get non si passano due parametri? Ad esempio una tupla come nell'esempio del libro o la Lettera come nell'esercizio e poi il valore da dare alla nuova chiave?
[CODE]>>> ConteggioLettere = {}
>>> for Lettera in "Mississippi":
... ConteggioLettere [Lettera] = ConteggioLettere.get \
... (Lettera, 0) + 1
...
>>> ConteggioLettere
{'i': 4, 'p': 2, 's': 4, 'M': 1}
>>> ConteggioLettere = ConteggioLettere.items()
>>> ConteggioLettere.sort()
>>> print ConteggioLettere
[('M', 1), ('i', 4), ('p', 2), ('s', 4)]
;)
Nella pyshell di linux va, sul portatile in ufficio oggi non andava. Ma la \ è un errore del libro?
cdimauro
05-11-2008, 22:39
Per me, pensare da informatico = pensare in termini di efficienza.
Follia pura, dunque, non abituarsi a ragionare in tal senso fin dagli inizi :O
:D
Un buon programmatore sostituisce ai "per me" la soddisfazione dei requisiti del problema, trovando possibilmente il giusto compromesso fra costi e benefici. :cool:
Un esempio del parametro del quale parli si può avere?
string.split('Qui, Quo, Qua', ', ')
Comunque questo significa che basta che uso l'oggetto con la notazione punto e la funzione che mi serve senza importare il modulo string?
Esatto. :cool:
Ascolto i tuoi consigli, la uso sempre la carta e la penna, però non mi tornano alcune cose..
In un messaggio t'ho scritto in maniera molto dettagliata come funziona la chiamata di una funzione ricorsiva (è il messaggio in cui parlavo di variabili "congelate"): devi soltanto applicare con carta e penna il procedimento, e vedrai che tutto ti tornerà chiaro.
A get non si passano due parametri?
In genere se ne passa uno, ma in questo caso è meglio non usare get, ma direttamente la sintassi:
Dizionario[Chiave]
al posto di Dizionario.get(Chiave)
E' molto più leggibile.
Io uso la get esclusivamente quando ho da specificare anche il valore di default che voglio se non viene trovata la chiave.
Ad esempio una tupla come nell'esempio del libro o la Lettera come nell'esercizio e poi il valore da dare alla nuova chiave?
Certamente. Con Python puoi mettere qualunque oggetto non mutabile come chiave. E qualunque oggetto (anche mutabile) come valore.
Tuple, stringhe, numeri sono oggetti immutabili.
Nella pyshell di linux va, sul portatile in ufficio oggi non andava.
A casa ho Windows, non Linux. :)
Ma la \ è un errore del libro?
No, serve per specificare che un'istruzione sta andando a capo e quindi bisogna proseguire nella riga seguente.
Con Python un'istruzione normalmente finisce a fine riga, e si considera quindi "chiusa". Se è troppo lunga la si "spezza" in più righe tramite \ appunto.
Se invece si sta elencando qualcosa (ad esempio l'elenco di una lista, di un dizionario, o i parametri di una funzione), il carattere \ non è necessario quando si va a capo.
~FullSyst3m~
05-11-2008, 22:54
string.split('Qui, Quo, Qua', ', ')
Non vedo nessuna differenza tra questo codice e quello senza parametri
In un messaggio t'ho scritto in maniera molto dettagliata come funziona la chiamata di una funzione ricorsiva (è il messaggio in cui parlavo di variabili "congelate"): devi soltanto applicare con carta e penna il procedimento, e vedrai che tutto ti tornerà chiaro.
Si lo ricordo quel messaggio. Allora, sono tornato indietro di qualche capitolo per ripassare meglio la ricorsione, e come esempio (visto che era nominato nel paragrafo degli interi lunghi) ho preso la funzione Fattoriale. Ecco il codice:
def Fattoriale (n):
if n == 0:
return 1
else:
FattorialeMenoUno = Fattoriale (n-1)
Risultato = n * FattorialeMenoUno
return Risultato
Scrivendo il fattoriale di un numero su carta e penna ho capito il procedimento, che di per sè è molto semplice, e anche simulando il funzionamento del codice su carta e penna non ho avuto nessun problema. Ho avuto la conferma che la ricorsione l'ho capita, le due cose che però non mi tornano (e che probabilmente non mi fanno quadrare nemmeno Fibonacci):
mettiamo caso che chiamo Fattoriale con n = 3. Siccome n != 0 si esegue il ramo dell'else. La prima istruzione ad essere eseguita è FattorialeMenoUno = Fattoriale (n-1). Allora, arrivati a questo punto n è uguale a 3 e Fattoriale viene richiamato con n = 2, quindi Risultato non viene eseguito. Visto che n è ancora diverso da 0 si rifà la stessa procedura, ma ora abbiamo n = 1 e cosi via fino a quanto n non è uguale a 0. Ora, quando n = 0 abbiamo le variabili "congelate" (cit.:asd:) n = 3, n = 2 e n = 1 giusto? Quello che mi chiedo è:
Risultato quando viene eseguito? E quando viene eseguito, n e FattorialeMenoUno che valore hanno?
Quando n = 0 viene eseguito l'if e la funzione dovrebbe terminare, invece continua a fare i suoi conti.
Infine, quel return, come nel caso di Fibonacci, se viene tolto dà il famoso errore. Ho capito il perchè, come ha spiegato VICIUS, però non capisco come ragiona l'interprete visto che il return è alla fine e non all'inizio. Questo significa che return dovrebbe tornare il valore finale, quando cioè l'ooperazione è già stata conclusa. Quindi perchè se metto il print al posto del return mi dà errore??
Sono banali queste domande per voi, lo so. Però se studiassi solo sul libro capirei tutto, però mi chiedo un sacco di cose, poi provo... e spuntano le domande! :D
In genere se ne passa uno, ma in questo caso è meglio non usare get, ma direttamente la sintassi:
Dizionario[Chiave]
al posto di Dizionario.get(Chiave)
E' molto più leggibile.
Io uso la get esclusivamente quando ho da specificare anche il valore di default che voglio se non viene trovata la chiave.
Uno? Nel libro c'è messo che si dovrebbe passare chiave e valore che si vuole tornare. Inoltre in quel caso (parlo per quel programmino) credo che il get serva per incrementare il conteggio. O no?. Comunque Dizionario[Chiave] serve per creare la chiave o per vedere il valore appartenente alla chiave.
A casa ho Windows, non Linux. :)
Nella shell di pyscript e di python in ufficio mi dava un errore (non ricordo quale al momento), nella pyshell su linux invece no :D
No, serve per specificare che un'istruzione sta andando a capo e quindi bisogna proseguire nella riga seguente.
Con Python un'istruzione normalmente finisce a fine riga, e si considera quindi "chiusa". Se è troppo lunga la si "spezza" in più righe tramite \ appunto.
Se invece si sta elencando qualcosa (ad esempio l'elenco di una lista, di un dizionario, o i parametri di una funzione), il carattere \ non è necessario quando si va a capo.
Ad esempio Fibonacci (12121212
1212) oppure ["ciao", "prova",
"tre"] sono validi?
~FullSyst3m~
06-11-2008, 18:26
Io Fibonacci l'ho scritta cosi, semplice e veloce:
def Fibonacci():
primo = 1
secondo = 1
partenza = 0
massimo = input ("Inserisci il numero del quale vuoi calcolare Fibonacci:")
while partenza < massimo:
prossimo = primo + secondo
primo = secondo
secondo = prossimo
partenza = partenza + 1
print "Il numero di Fibonacci e'", primo
Qua si capisce al volo, ma nell'esempio ricorsivo e con il dizionario è un casino seguirla.
P.S: tornando al discorso del return, qua pure ci sono delle operazioni, ma anche senza return non mi restituisce errore come nell'altro caso. Perchè?
Comunque Vincenzo, ora dopo aver scritto questo codice non capisco ancora di più perchè nel tuo codice hai scritto Temp = 3 (che corrisponde al mio partenza = 0). Io con partenza = 0 ottengo 55 con Fibonacci (10)
^TiGeRShArK^
06-11-2008, 19:19
l'algoritmo ricorsivo correttamente implementato è il + chiaro però.
Ecco come viene in haskell (rigorosamente rubato dal web dato che ho provato solo una volta ad impararlo e ho capito che i linguaggi funzionali puri non fanno x me :p)
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
Più chiaro di così non si può scrivere direi :read:
~FullSyst3m~
06-11-2008, 19:23
l'algoritmo ricorsivo correttamente implementato è il + chiaro però.
Ecco come viene in haskell (rigorosamente rubato dal web dato che ho provato solo una volta ad impararlo e ho capito che i linguaggi funzionali puri non fanno x me :p)
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
Più chiaro di così non si può scrivere direi :read:
Anche in Python si può scrivere cosi chiaro ;) Il punto della discussione non è questo però, rileggi i miei due post di sopra ;) Comunque a me sembra più chiaro quello iterativo che quello ricorsivo, ad esempio il codice che usa il dizionario mi fa solo confondere
^TiGeRShArK^
06-11-2008, 19:26
Anche in Python si può scrivere cosi chiaro ;) Il punto della discussione non è questo però, rileggi i miei due post di sopra ;) Comunque a me sembra più chiaro quello iterativo che quello ricorsivo, ad esempio il codice che usa il dizionario mi fa solo confondere
te l'aveva già spiegato il perchè di temp = 3 :fagiano:
perchè lui restituisce 1 se n è <= 2 quindi entra nel while solo da 3 in su....
Vincenzo1968
06-11-2008, 19:30
l'algoritmo ricorsivo correttamente implementato è il + chiaro però.
Ecco come viene in haskell (rigorosamente rubato dal web dato che ho provato solo una volta ad impararlo e ho capito che i linguaggi funzionali puri non fanno x me :p)
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
Più chiaro di così non si può scrivere direi :read:
Eleganza e leggibilità a tutti i costi? Nel caso del calcolo dei numeri di Fibonacci, è follia pura utilizzare un algoritmo ricorsivo. Guarda cosa succede nella mia macchina se passo 1000 come argomento alla funzione suggerita nel libro:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciRecursive.jpg
Con la funzione iterativa che ho proposto, il risulltato viene calcolato senza nessun problema:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciNonRecursive.jpg
Qualsiasi buon manuale di algoritmi(per esempio, il Sedgewick ;)) ti spiega perchè, a proposito di Fibonacci, è follia pura, e dal punto di vista della complessità computazionale e da quello dello spreco di memoria, utilizzare un algoritmo ricorsivo. (La stessa cosa vale, per esempio, nel calcolo del fattoriale).
La mia macchina:
AMD Athlon(tm) 64 X2
Dual Core Processor 4800+
2.50 GHz
896 MB di RAM
Microsoft Windows XP Professional (32 bit)
Service Pack 3
^TiGeRShArK^
06-11-2008, 19:33
Eleganza e leggibilità a tutti i costi? Nel caso del calcolo dei numeri di Fibonacci, è follia pura utilizzare un algoritmo ricorsivo. Guarda cosa succede nella mia macchina se passo 1000 come argomento alla funzione suggerita nel libro:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciRecursive.jpg
Con la funzione iterativa che ho proposto, il risulltato viene calcolato senza nessun problema:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciNonRecursive.jpg
Qualsiasi buon manuale di algoritmi(per esempio, il Sedgewick ;)) ti spiega perchè è follia pura, e dal punto di vista della complessità computazionale e da quello dello spreco di memoria, utilizzare un algoritmo ricorsivo. (La stessa cosa vale, per esempio, nel calcolo del fattoriale).
Non è follia pura se lo scopo è imparare a programmare.
Ovviamente non lo utilizzerai mai in un'applicazione reale, ma trovare l'algoritmo + leggibile è SEMPRE cosa buona e giusta dato che si suppone che il codice ci passi + tempo a leggerlo che a scriverlo e che lavori in un team fatto da N persone che se si mettono a scrivere cose oscene tanto x ottimizzare dove non necessario non ci capisce + nessuno una mazza.
In questo caso non mi pare che ci sia un modo + leggibile per scrivere l'algoritmo di fibonacci e che quindi spieghi in una sola occhiata quello che deve fare.
...molto didattico oserei dire :p
~FullSyst3m~
06-11-2008, 19:41
te l'aveva già spiegato il perchè di temp = 3 :fagiano:
perchè lui restituisce 1 se n è <= 2 quindi entra nel while solo da 3 in su....
Si, l'ho capito cosa ha detto lui, ma non capisco il perchè. Comunque guardate cosa dà pyshell in output quando chiamo la funzione con il dizionario:
print Fibonacci (10)
55
None
Quel none è dovuto al famoso secondo return
~FullSyst3m~
06-11-2008, 19:45
Eleganza e leggibilità a tutti i costi? Nel caso del calcolo dei numeri di Fibonacci, è follia pura utilizzare un algoritmo ricorsivo. Guarda cosa succede nella mia macchina se passo 1000 come argomento alla funzione suggerita nel libro:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciRecursive.jpg
Con la funzione iterativa che ho proposto, il risulltato viene calcolato senza nessun problema:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciNonRecursive.jpg
Qualsiasi buon manuale di algoritmi(per esempio, il Sedgewick ;)) ti spiega perchè, a proposito di Fibonacci, è follia pura, e dal punto di vista della complessità computazionale e da quello dello spreco di memoria, utilizzare un algoritmo ricorsivo. (La stessa cosa vale, per esempio, nel calcolo del fattoriale).
La mia macchina:
AMD Athlon(tm) 64 X2
Dual Core Processor 4800+
2.50 GHz
896 MB di RAM
Microsoft Windows XP Professional (32 bit)
Service Pack 3
Ecco Fattoriale in modo ricorsivo, come la scriveresti tu in modo iterativo:
def Fattoriale (n):
if n == 0:
return 1
else:
FattorialeMenoUno = Fattoriale (n-1)
Risultato = n * FattorialeMenoUno
return Risultato
Vincenzo1968
06-11-2008, 19:47
Non è follia pura se lo scopo è imparare a programmare.
Ovviamente non lo utilizzerai mai in un'applicazione reale, ma trovare l'algoritmo + leggibile è SEMPRE cosa buona e giusta dato che si suppone che il codice ci passi + tempo a leggerlo che a scriverlo e che lavori in un team fatto da N persone che se si mettono a scrivere cose oscene tanto x ottimizzare dove non necessario non ci capisce + nessuno una mazza.
In questo caso non mi pare che ci sia un modo + leggibile per scrivere l'algoritmo di fibonacci e che quindi spieghi in una sola occhiata quello che deve fare.
...molto didattico oserei dire :p
Comunque non è molto azzeccato come esempio per spiegare la ricorsione o i dizionari, visto anche che l'autore del libro la considera Una buona soluzione :eekk:
~FullSyst3m~
06-11-2008, 19:47
Mentre riquoto le altre cose che mi interessano, la notte non ci dormo:
P.S: tornando al discorso del return, qua (riferito a Fibonacci iterativo scritto da me) pure ci sono delle operazioni, ma anche senza return non mi restituisce errore come nell'altro caso. Perchè?
string.split('Qui, Quo, Qua', ', ')
Non vedo nessuna differenza tra questo codice e quello senza parametri
In un messaggio t'ho scritto in maniera molto dettagliata come funziona la chiamata di una funzione ricorsiva (è il messaggio in cui parlavo di variabili "congelate"): devi soltanto applicare con carta e penna il procedimento, e vedrai che tutto ti tornerà chiaro.
Si lo ricordo quel messaggio. Allora, sono tornato indietro di qualche capitolo per ripassare meglio la ricorsione, e come esempio (visto che era nominato nel paragrafo degli interi lunghi) ho preso la funzione Fattoriale. Ecco il codice:
def Fattoriale (n):
if n == 0:
return 1
else:
FattorialeMenoUno = Fattoriale (n-1)
Risultato = n * FattorialeMenoUno
return Risultato
Scrivendo il fattoriale di un numero su carta e penna ho capito il procedimento, che di per sè è molto semplice, e anche simulando il funzionamento del codice su carta e penna non ho avuto nessun problema. Ho avuto la conferma che la ricorsione l'ho capita, le due cose che però non mi tornano (e che probabilmente non mi fanno quadrare nemmeno Fibonacci):
mettiamo caso che chiamo Fattoriale con n = 3. Siccome n != 0 si esegue il ramo dell'else. La prima istruzione ad essere eseguita è FattorialeMenoUno = Fattoriale (n-1). Allora, arrivati a questo punto n è uguale a 3 e Fattoriale viene richiamato con n = 2, quindi Risultato non viene eseguito. Visto che n è ancora diverso da 0 si rifà la stessa procedura, ma ora abbiamo n = 1 e cosi via fino a quanto n non è uguale a 0. Ora, quando n = 0 abbiamo le variabili "congelate" (cit.:asd:) n = 3, n = 2 e n = 1 giusto? Quello che mi chiedo è:
Risultato quando viene eseguito? E quando viene eseguito, n e FattorialeMenoUno che valore hanno?
Quando n = 0 viene eseguito l'if e la funzione dovrebbe terminare, invece continua a fare i suoi conti.
Infine, quel return, come nel caso di Fibonacci, se viene tolto dà il famoso errore. Ho capito il perchè, come ha spiegato VICIUS, però non capisco come ragiona l'interprete visto che il return è alla fine e non all'inizio. Questo significa che return dovrebbe tornare il valore finale, quando cioè l'ooperazione è già stata conclusa. Quindi perchè se metto il print al posto del return mi dà errore??
Sono banali queste domande per voi, lo so. Però se studiassi solo sul libro capirei tutto, però mi chiedo un sacco di cose, poi provo... e spuntano le domande! :D
In genere se ne passa uno, ma in questo caso è meglio non usare get, ma direttamente la sintassi:
Dizionario[Chiave]
al posto di Dizionario.get(Chiave)
E' molto più leggibile.
Io uso la get esclusivamente quando ho da specificare anche il valore di default che voglio se non viene trovata la chiave.
Uno? Nel libro c'è messo che si dovrebbe passare chiave e valore che si vuole tornare. Inoltre in quel caso (parlo per quel programmino) credo che il get serva per incrementare il conteggio. O no?. Comunque Dizionario[Chiave] serve per creare la chiave o per vedere il valore appartenente alla chiave.
A casa ho Windows, non Linux. :)
Nella shell di pyscript e di python in ufficio mi dava un errore (non ricordo quale al momento), nella pyshell su linux invece no :D
No, serve per specificare che un'istruzione sta andando a capo e quindi bisogna proseguire nella riga seguente.
Con Python un'istruzione normalmente finisce a fine riga, e si considera quindi "chiusa". Se è troppo lunga la si "spezza" in più righe tramite \ appunto.
Se invece si sta elencando qualcosa (ad esempio l'elenco di una lista, di un dizionario, o i parametri di una funzione), il carattere \ non è necessario quando si va a capo.
Ad esempio Fibonacci (12121212
1212) oppure ["ciao", "prova",
"tre"] sono validi?
~FullSyst3m~
06-11-2008, 19:49
Comunque non è molto azzeccato come esempio per spiegare la ricorsione, visto anche che l'autore del libro la considera Una buona soluzione :eekk:
Cerchiamo di concentrarci su quello che non mi quadra prima altrimenti non ne esco più :D
Poi possiamo pure parlare di come fare la carne in modo iterativo :asd:
Vincenzo1968
06-11-2008, 19:49
Ecco Fattoriale in modo ricorsivo, come la scriveresti tu in modo iterativo:
def Fattoriale (n):
if n == 0:
return 1
else:
FattorialeMenoUno = Fattoriale (n-1)
Risultato = n * FattorialeMenoUno
return Risultato
Io la scriverei esattamente nel modo in cui l'ho scritta prima. Né più né meno, senza riri né ai né bai, né scù né passiddà ;)
~FullSyst3m~
06-11-2008, 19:51
Io la scriverei esattamente nel modo in cui l'ho scritta prima. Né più né meno, senza riri né ai né bai, né scù né passiddà ;)
Non ho capito un cavolo.. comunque scrivi il codice iterativo allora...
Vincenzo1968
06-11-2008, 19:54
Non ho capito un cavolo.. comunque scrivi il codice iterativo allora...
Scusami Full,
non m'ero accorto che si trattava del fattoriale. Pensavo fosse un'ulteriore versione ricorsiva di Fibonacci.
Fra un po' comincia Santoro. Più tardi ti posto la soluzione iterativa del fattoriale. Ciao ;)
~FullSyst3m~
06-11-2008, 21:14
Scusami Full,
non m'ero accorto che si trattava del fattoriale. Pensavo fosse un'altra versione iterativa di Fibonacci.
Fra un po' comincia Santoro. Più tardi ti posto la soluzione iterativa del fattoriale. Ciao ;)
Io invece ho la Perego :sbav: A dopo allora ;)
Comunque valgono sempre le altre cose scritte negli altri post, se non mi tolgo questi dubbi non dormo la notte :muro: :muro:
Vincenzo1968
06-11-2008, 22:38
Ecco Fattoriale in modo ricorsivo, come la scriveresti tu in modo iterativo:
def Fattoriale (n):
if n == 0:
return 1
else:
FattorialeMenoUno = Fattoriale (n-1)
Risultato = n * FattorialeMenoUno
return Risultato
Eqque qua:
def Fattoriale (n):
if n < 0:
print "Che cacchio fai? n dev'essere >= 0."
return -1
Risultato = 1;
i = 1;
while i <= n:
Risultato *= i
i += 1
return Risultato
print Fattoriale(1000)
Ancora una volta, se utilizzo la versione ricorsiva che hai postato tu, con n = 1000, il programma ha problemi di memoria; la versione iterativa che ti ho postato, invece, calcola tranquillamente il risultato ;)
Vincenzo1968
06-11-2008, 22:41
Io invece ho la Perego :sbav: A dopo allora ;)
Comunque valgono sempre le altre cose scritte negli altri post, se non mi tolgo questi dubbi non dormo la notte :muro: :muro:
Personaggi come la Perego, come Maria De Filippi e compagnia bella, non favoriscono lo sviluppo delle facoltà mentali ;)
P.S. Però è bona(la Perego, dico), questo si ;)
Eqque qua:
def Fattoriale (n):
if n < 0:
print "Che cacchio fai? n dev'essere >= 0."
return -1
Non stai usando C. Molto meglio lanciare una eccezione in questi casi :)
Vincenzo1968
06-11-2008, 23:10
Non stai usando C. Molto meglio lanciare una eccezione in questi casi :)
Ohé Vicius,
proprio te cercavo.
Intanto grazie per il suggerimento :)
Volevo chiederti se puoi postare le soluzioni(sia Fibonacci che Fattoriale) equivalenti in Ruby (in versione e ricorsiva e iterativa).
Grazie ;)
Domai mattina metto giù qualche riga poi te le passo.
Vincenzo1968
06-11-2008, 23:23
Domai mattina metto giù qualche riga poi te le passo.
Grazie mille ;)
DanieleC88
06-11-2008, 23:36
Si lo ricordo quel messaggio. Allora, sono tornato indietro di qualche capitolo per ripassare meglio la ricorsione, [...] Quello che mi chiedo è:
Risultato quando viene eseguito? E quando viene eseguito, n e FattorialeMenoUno che valore hanno?
Aspe', non hai capito benissimo, il flusso d'esecuzione quando tu fai una chiamata ad una funzione non viene spezzato per sempre; viene interrotto per consentire alla chiamata di avere luogo, ed alla fine riprende dall'istruzione immediatamente successiva.
Prova a rifare il ragionamento davanti alla carta tenendo conto di questo, e se ancora non ti è del tutto chiaro prova a simulare una pila: sei nel tuo programma principale e chiami la funzione per il calcolo dell'ennesimo numero di Fibonacci; ad ogni chiamata di funzione disegni un quadratino e lo metti in cima alla pila dei quadratini eventualmente già esistenti; quando una funzione termina la sua esecuzione, lo cancelli.
Ultima cosa: ogni funzione che viene invocata vive in un suo spazio e non interferisce con le altre; idealmente, la tua funzione ricorsiva replica se stessa tante volte quante ne sono necessarie ed aspetta che le sue repliche finiscano i propri calcoli prima di uscire.
ciao ;)
Vincenzo1968
06-11-2008, 23:38
Aspe', non hai capito benissimo, il flusso d'esecuzione quando tu fai una chiamata ad una funzione non viene spezzato per sempre; viene interrotto per consentire alla chiamata di avere luogo, ed alla fine riprende dall'istruzione immediatamente successiva.
Prova a rifare il ragionamento davanti alla carta tenendo conto di questo, e se ancora non ti è del tutto chiaro prova a simulare una pila: sei nel tuo programma principale e chiami la funzione per il calcolo dell'ennesimo numero di Fibonacci; ad ogni chiamata di funzione disegni un quadratino e lo metti in cima alla pila dei quadratini eventualmente già esistenti; quando una funzione termina la sua esecuzione, lo cancelli.
Ultima cosa: ogni funzione che viene invocata vive in un suo spazio e non interferisce con le altre; idealmente, la tua funzione ricorsiva replica se stessa tante volte quante ne sono necessarie ed aspetta che le sue repliche finiscano i propri calcoli.
ciao ;)
Sperando che non esaurisca la memoria mandando in tilt il programma, com'è successo a me per n = 1000.
;)
DanieleC88
06-11-2008, 23:41
Esatto, in particolare per Fibonacci che chiama se stessa due volte ad ogni invocazione. :D
Vincenzo1968
06-11-2008, 23:44
Esatto, in particolare per Fibonacci che chiama se stessa due volte ad ogni invocazione. :D
Il che è un disastro, come spiega Sedgewick(che di algoritmi se ne intende, fu allievo di Knuth ;)), anche dal punto di vista delle prestazioni :D
def fib(n)
return n if (0..1).include? n
fib(n-2) + fib(n-1)
end
def fib_i(n)
curr, succ = 0, 1
n.times do
curr, succ = succ, curr + succ
end
curr
end
def fact(n)
return 1 if n == 0
n * fact(n-1)
end
def fact_i(n)
f = 1
1.upto n do |i|
f *= i
end
f
end
puts fib(10)
puts fib_i(10)
puts fact(10)
puts fact_i(10)
Vincenzo1968
07-11-2008, 00:20
Azz!
Avevi detto domani mattina ma non me l'aspettavo cosi presto.
Grazie mille :D
^TiGeRShArK^
07-11-2008, 01:36
Sperando che non esaurisca la memoria mandando in tilt il programma, com'è successo a me per n = 1000.
;)
in quel modo non esaurisci la memoria, ma solo lo stack, che mi pare cosa ben diversa...
Se controlli l'heap in quel momento trovi una marea di spazio...
Il problema è, piuttosto, che le chiamate ricorsive occupano spazio nello stack anzichè nell'heap.
E che comunque sono meno efficienti per un applicazione reale (e non didattica come questa :p)
P.S. che hanno fatto ad anno zero che io sono scappato quasi subito? :fagiano:
^TiGeRShArK^
07-11-2008, 01:43
def fib(n)
return n if (0..1).include? n
fib(n-2) + fib(n-1)
end
def fib_i(n)
curr, succ = 0, 1
n.times do
curr, succ = succ, curr + succ
end
curr
end
def fact(n)
return 1 if n == 0
n * fact(n-1)
end
def fact_i(n)
f = 1
1.upto n do |i|
f *= i
end
f
end
puts fib(10)
puts fib_i(10)
puts fact(10)
puts fact_i(10)
quanto a compattezza di codice ruby mi sa che non ha rivali :D
...ma tu usi ruby così x hobby o anche x lavoro? :fagiano:
io l'ho usato, insieme a python, solo una volta x lavoro (x un tweaking di java RT he scatenava delle azioni in base ai commit su CVS :p)
...ma tu usi ruby così x hobby o anche x lavoro? :fagiano:
Con ruby ci gioco soltanto.
cdimauro
07-11-2008, 07:46
Eleganza e leggibilità a tutti i costi? Nel caso del calcolo dei numeri di Fibonacci, è follia pura utilizzare un algoritmo ricorsivo. Guarda cosa succede nella mia macchina se passo 1000 come argomento alla funzione suggerita nel libro:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciRecursive.jpg
Con la funzione iterativa che ho proposto, il risulltato viene calcolato senza nessun problema:
http://www.guidealgoritmi.it/images/ImgForums/FibonacciNonRecursive.jpg
Qualsiasi buon manuale di algoritmi(per esempio, il Sedgewick ;)) ti spiega perchè, a proposito di Fibonacci, è follia pura, e dal punto di vista della complessità computazionale e da quello dello spreco di memoria, utilizzare un algoritmo ricorsivo. (La stessa cosa vale, per esempio, nel calcolo del fattoriale).
La mia macchina:
AMD Athlon(tm) 64 X2
Dual Core Processor 4800+
2.50 GHz
896 MB di RAM
Microsoft Windows XP Professional (32 bit)
Service Pack 3
Vedo che ci metti proprio tutti i mezzi per far vedere che NON sei un buon informatico.
Hai presente il significato di "requisito del problema"? Ecco, il thread nasce perché ~FullSyst3m~ DEVE IMPARARE A PROGRAMMARE, semmai ti fosse sfuggito.
E per far questo sta semplicemente studiando un libro che PROPONE DEI BEN PRECISI ESERCIZI CHE DEVE SVOLGERE.
Quindi se l'esercizio gli dice di risolvere Fibonacci in maniera ricorsiva e usando i dizionari (ti sembrerà strano, ma questa soluzione coi dizionari HA UN BEN PRECISO MOTIVO DI ESISTERE), beh, DEVE FARE COSI'.
In ogni caso LE PRESTAZIONI NON SONO UN REQUISITO IMPLICITO DA SODDISFARE PER OGNI PROBLEMA CHE DEV'ESSERE RISOLTO.
Vediamo se lo capisci una buona volta.
Mentre riquoto le altre cose che mi interessano, la notte non ci dormo:
Non vedo nessuna differenza tra questo codice e quello senza parametri
Si lo ricordo quel messaggio. Allora, sono tornato indietro di qualche capitolo per ripassare meglio la ricorsione, e come esempio (visto che era nominato nel paragrafo degli interi lunghi) ho preso la funzione Fattoriale. Ecco il codice:
def Fattoriale (n):
if n == 0:
return 1
else:
FattorialeMenoUno = Fattoriale (n-1)
Risultato = n * FattorialeMenoUno
return Risultato
Scrivendo il fattoriale di un numero su carta e penna ho capito il procedimento, che di per sè è molto semplice, e anche simulando il funzionamento del codice su carta e penna non ho avuto nessun problema. Ho avuto la conferma che la ricorsione l'ho capita, le due cose che però non mi tornano (e che probabilmente non mi fanno quadrare nemmeno Fibonacci):
mettiamo caso che chiamo Fattoriale con n = 3. Siccome n != 0 si esegue il ramo dell'else. La prima istruzione ad essere eseguita è FattorialeMenoUno = Fattoriale (n-1). Allora, arrivati a questo punto n è uguale a 3 e Fattoriale viene richiamato con n = 2, quindi Risultato non viene eseguito. Visto che n è ancora diverso da 0 si rifà la stessa procedura, ma ora abbiamo n = 1 e cosi via fino a quanto n non è uguale a 0. Ora, quando n = 0 abbiamo le variabili "congelate" (cit.:asd:) n = 3, n = 2 e n = 1 giusto? Quello che mi chiedo è:
Risultato quando viene eseguito? E quando viene eseguito, n e FattorialeMenoUno che valore hanno?
Quando n = 0 viene eseguito l'if e la funzione dovrebbe terminare, invece continua a fare i suoi conti.
Infine, quel return, come nel caso di Fibonacci, se viene tolto dà il famoso errore. Ho capito il perchè, come ha spiegato VICIUS, però non capisco come ragiona l'interprete visto che il return è alla fine e non all'inizio. Questo significa che return dovrebbe tornare il valore finale, quando cioè l'ooperazione è già stata conclusa. Quindi perchè se metto il print al posto del return mi dà errore??
Sono banali queste domande per voi, lo so. Però se studiassi solo sul libro capirei tutto, però mi chiedo un sacco di cose, poi provo... e spuntano le domande! :D
Uno? Nel libro c'è messo che si dovrebbe passare chiave e valore che si vuole tornare. Inoltre in quel caso (parlo per quel programmino) credo che il get serva per incrementare il conteggio. O no?. Comunque Dizionario[Chiave] serve per creare la chiave o per vedere il valore appartenente alla chiave.
Nella shell di pyscript e di python in ufficio mi dava un errore (non ricordo quale al momento), nella pyshell su linux invece no :D
Ad esempio Fibonacci (12121212
1212) oppure ["ciao", "prova",
"tre"] sono validi?
Adesso non ho tempo perché vado di corsa e non posso dedicare troppo tempo al forum.
Per quanto riguarda le funzioni ricorsive, quando simili con carta e penna devi ricordati che ogni chiamata alla stessa funzione CONGELA le variabili usate in quel preciso momento, e ne crea di nuove coi nuovi valori per la nuova esecuzione della stessa; quando l'ultima funzione invoca termina, le sue variabili vengono "buttate via", e l'esecuzione riprende dall'ultima invocazione della funzione, con le sue variabile che vengono "SCONGELATE".
Prova, e vedrai che i conti ti tornerai tutti.
Poi se usassi SPE col debugger seguendo l'esecuzione passo passo vedresti immediatamente quel che succede.
Alla prossima.
quanto a compattezza di codice ruby mi sa che non ha rivali :D
...ma tu usi ruby così x hobby o anche x lavoro? :fagiano:
io l'ho usato, insieme a python, solo una volta x lavoro (x un tweaking di java RT he scatenava delle azioni in base ai commit su CVS :p)
Anche Python non scherza: http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=python&lang2=ruby Siamo lì, anzi forse mediamente è un pelino in vantaggio Python. ;)
Comunque adesso non ho tempo di postare le versioni Python.
Anzi, lasciamolo come esercizio a ~FullSyst3m~. :D
~FullSyst3m~
07-11-2008, 08:05
Aspe', non hai capito benissimo, il flusso d'esecuzione quando tu fai una chiamata ad una funzione non viene spezzato per sempre; viene interrotto per consentire alla chiamata di avere luogo, ed alla fine riprende dall'istruzione immediatamente successiva.
Si questo l'ho capito, infatti ho scritto che non capisco cosa succede dopo che n = 0 e la funzione esce ritornando 1 (parlo di Fattoriale)
Prova a rifare il ragionamento davanti alla carta tenendo conto di questo, e se ancora non ti è del tutto chiaro prova a simulare una pila: sei nel tuo programma principale e chiami la funzione per il calcolo dell'ennesimo numero di Fibonacci; ad ogni chiamata di funzione disegni un quadratino e lo metti in cima alla pila dei quadratini eventualmente già esistenti; quando una funzione termina la sua esecuzione, lo cancelli.
Provato a fare pure questo. Forse non mi sono spiegato, il problema non è la ricorsione in sè, ma capire quelle due cose e cioè:
"Risultato quando viene eseguito? E quando viene eseguito, n e FattorialeMenoUno che valore hanno?"
Ultima cosa: ogni funzione che viene invocata vive in un suo spazio e non interferisce con le altre; idealmente, la tua funzione ricorsiva replica se stessa tante volte quante ne sono necessarie ed aspetta che le sue repliche finiscano i propri calcoli prima di uscire.
Queste cose le so, non è questo il problema;)
~FullSyst3m~
07-11-2008, 08:06
Per quanto riguarda le funzioni ricorsive, quando simili con carta e penna devi ricordati che ogni chiamata alla stessa funzione CONGELA le variabili usate in quel preciso momento, e ne crea di nuove coi nuovi valori per la nuova esecuzione della stessa; quando l'ultima funzione invoca termina, le sue variabili vengono "buttate via", e l'esecuzione riprende dall'ultima invocazione della funzione, con le sue variabile che vengono "SCONGELATE".
Prova, e vedrai che i conti ti tornerai tutti.
Ho già provato e mi è tutto chiaro, tranne quelle due cose che ho scritto (sto parlando del Fattoriale)
Poi se usassi SPE col debugger seguendo l'esecuzione passo passo vedresti immediatamente quel che succede.
Fosse per me lo userei, sono impossibilitato ad usare SPE al momento
Anche Python non scherza: http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=python&lang2=ruby Siamo lì, anzi forse mediamente è un pelino in vantaggio Python. ;)
Comunque adesso non ho tempo di postare le versioni Python.
Anzi, lasciamolo come esercizio a ~FullSyst3m~. :D
Versioni Python di cosa? Che esercizio?
~FullSyst3m~
07-11-2008, 10:53
Allora, riguardo il Fattoriale ho scritto l'esecuzione e i valori delle varie variabili a mano, in modo molto simile al libro. Le cose tornano, ma l'unica cosa che non capisco è che quando n = 0 ritorna 1, questo uno però poi viene moltiplicato per n = 1 e cosi via. Arrivato a n = 0 la funzione non dovrebbe terminare e basta? E poi perchè viene usato il valore di ritorno 1 per moltiplicarlo a n = 1?
Comunque nel libro nel diagramma c'è messo n = 1 FattorialeMenoUno = 1. Il FattorialeMenoUno di 1 è 0 no?
Vincenzo, riguardo il tuo codice, perchè i ; finali? E *= i sta a significare = *i? Ma cosa viene moltiplicato per i? Risultato? Ancora con questa sintassi non c'ho molta confidenza, nel libro ho studiato Risultato = Risultato * i
Allora, riguardo il Fattoriale ho scritto l'esecuzione e i valori delle varie variabili a mano, in modo molto simile al libro. Le cose tornano, ma l'unica cosa che non capisco è che quando n = 0 ritorna 1, questo uno però poi viene moltiplicato per n = 1 e cosi via. Arrivato a n = 0 la funzione non dovrebbe terminare e basta? E poi perchè viene usato il valore di ritorno 1 per moltiplicarlo a n = 1?
Comunque nel libro nel diagramma c'è messo n = 1 FattorialeMenoUno = 1. Il FattorialeMenoUno di 1 è 0 no?
No attenzione. La definizione di fattoriale specifica chiaramente che quando n = 0 si deve ritornare 1 mentre in tutti gli altri casi è n moltiplicato per il fattoriale di n-1. Da wikipedia:
http://upload.wikimedia.org/math/4/f/a/4fa36f9547a3a395416a263a4f356b7a.png
~FullSyst3m~
07-11-2008, 11:59
No attenzione. La definizione di fattoriale specifica chiaramente che quando n = 0 si deve ritornare 1 mentre in tutti gli altri casi è n moltiplicato per il fattoriale di n-1. Da wikipedia:
http://upload.wikimedia.org/math/4/f/a/4fa36f9547a3a395416a263a4f356b7a.png
Si si questo lo so, è scritto pure nel libro. Dico solo che 1-1 fa 0. Poi 0 è uguale a 1, ok, però fa 0. Capito che voglio dire? Comunque la mia domanda non ha ancora risposta: perchè quando n = 0 invece di terminare la funzione continua e usa il valore di ritorno 1 per fare i calcoli?
P.S: VICIUS ancora non abbiamo finito il discorso dei return, leggi più sopra
Si si questo lo so, è scritto pure nel libro. Dico solo che 1-1 fa 0. Poi 0 è uguale a 1, ok, però fa 0.
Non proprio ma forse è colpa mia che sto dando troppe cose per scontate. Cerca di essere il più chiaro possibile su quello che non hai chiaro.
Capito che voglio dire? Comunque la mia domanda non ha ancora risposta: perchè quando n = 0 invece di terminare la funzione continua e usa il valore di ritorno 1 per fare i calcoli?
La chiamata fattoriale(0) termina nel preciso istante in cui arriva al return 1 non fa nessun calcolo. Sono tutte le altre chiamate, che sono ancora in attesa di una valore da moltiplicare, che che poco per volta eseguono il calcolo completo del fattoriale.
~FullSyst3m~
07-11-2008, 12:21
Non proprio ma forse è colpa mia che sto dando troppe cose per scontate. Cerca di essere il più chiaro possibile su quello che non hai chiaro.
Non dai nulla di scontato, quello che hai scritto è scritto pure sul libro. Quello che dico è che se n = 1, allora FattorialeMenoUno = 0. Anche se poi 0 vale 1, sul libro hanno scritto 1 sicuramente per questo.
La chiamata fattoriale(0) termina nel preciso istante in cui arriva al return 1 non fa nessun calcolo. Sono tutte le altre chiamate, che sono ancora in attesa di una valore da moltiplicare, che che poco per volta eseguono il calcolo completo del fattoriale.
Quindi l'1 che viene moltiplicato ad n = 1 non è quello del return, ma quell di n = 0 che corrisponde ad 1? Comunque le chiamate fin quando n != 0 rimangono ferme a FattorialeMenoUno e poi quando n = 0 fanno i vari calcoli di n con Risultato. Correggetemi se sbaglio ;)
Vincenzo1968
07-11-2008, 14:53
...
Vedo che ci metti proprio tutti i mezzi per far vedere che NON sei un buon informatico.
Hai presente il significato di "requisito del problema"? Ecco, il thread nasce perché ~FullSyst3m~ DEVE IMPARARE A PROGRAMMARE, semmai ti fosse sfuggito.
E per far questo sta semplicemente studiando un libro che PROPONE DEI BEN PRECISI ESERCIZI CHE DEVE SVOLGERE.
Quindi se l'esercizio gli dice di risolvere Fibonacci in maniera ricorsiva e usando i dizionari (ti sembrerà strano, ma questa soluzione coi dizionari HA UN BEN PRECISO MOTIVO DI ESISTERE), beh, DEVE FARE COSI'.
In ogni caso LE PRESTAZIONI NON SONO UN REQUISITO IMPLICITO DA SODDISFARE PER OGNI PROBLEMA CHE DEV'ESSERE RISOLTO.
Vediamo se lo capisci una buona volta.
Adesso non ho tempo perché vado di corsa e non posso dedicare troppo tempo al forum.
...
Uh quante certezze che hai! Come te le invidio :cool:
La prima certezza è che io NON sono un buon informatico. Ma questa non è una novità. Non è la prima volta che me lo dici e io non ho mai affermato di essere un buon informatico e, anzi, ho sempre detto il contrario.
In quanto alle prestazioni, parlando dell'esempio riportato nel libro su Fibonacci, ho semplicemente rilevato che non mi pare azzeccato. È l'autore a parlare di prestazioni:
Se hai fatto qualche prova con la funzione di Fibonacci nella sezione 5.7 avrai notato che man mano che l'argomento passato alla funzione cresce il tempo trascorso prima di ottenere il risultato aumenta molto rapidamente. Mentre Fibonacci(20) termina quasi istantaneamente Fibonacci(30) impiega qualche secondo e Fibonacci(40) impiega un tempo lunghissimo.
Per comprenderne il motivo consideriamo questo grafico delle chiamate per la funzione Fibonacci con n=4:
...
Un grafico delle chiamate mostra una serie di frame (uno per ogni funzione) con linee che collegano ciascun frame alle funzioni chiamate. A iniziare dall'alto Fibonacci con n=4 chiama Fibonacci con n=3 e n=2. A sua volta Fibonacci con n=3 chiama Fibonacci con n=2 e n=1. E così via.
Se conti il numero di volte in cui Fibonacci(0) e Fibonacci(1) sono chiamate ti accorgerai facilmente che questa soluzione è evidentemente inefficiente e le sue prestazioni tendono a peggiorare man mano che l'argomento diventa più grande.
Una buona soluzione è quella di tenere traccia in un dizionario di tutti i vanlori già calcolati per evitare il ricalcolo in tempi successivi. Un valore che viene memorizzato per un uso successivo è chiamato suggerimento. Ecco un'implementazione di Fibonacci fatta usando i "suggerimenti":
Precedenti = {0:1, 1:1}
def Fibonacci(n):
if Precedenti.has_key(n):
return Precedenti[n]
else:
NuovoValore = Fibonacci(n-1) + Fibonacci(n-2)
Precedenti[n] = NuovoValore
return NuovoValore
Come vedi, l'autore dà come buona soluzione, relativamente alle prestazioni, la versione ricorsiva con dizionario. Il che è una gran cazzata.
Continuo a pensare che avrebbe dovuto usare, per illustrare il funzionamento dei dizionari, qualunque altra cosa, non certo Fibonacci. :)
Come vedi, l'autore dà come buona soluzione, relativamente alle prestazioni, la versione ricorsiva con dizionario. Il che è una gran cazzata.
Continuo a pensare che avrebbe dovuto usare, per illustrare il funzionamento dei dizionari, qualunque altra cosa, non certo Fibonacci. :)
Non vedo cosa ci sia di strano. Un accesso ad un dizionario è infinitamente più veloce di un ciclo che fa somme a migliaia di cifre.
Vincenzo1968
07-11-2008, 15:32
Non vedo cosa ci sia di strano. Un accesso ad un dizionario è infinitamente più veloce di un ciclo che fa somme a migliaia di cifre.
Ehm Vicius,
scusa ma, nel programma proposto dall'autore del libro, si utilizza un dizionario con i valori già presenti, o, ad ogni chiamata ricorsiva, si fa la somma e si aggiorna il dizionario?
Peccato che non possa fare dei test, perché, come abbiamo visto, la versione ricorsiva, sulla mia macchina, esaurisce lo stack per valori >= 1000.
Ehm Vicius,
scusa ma, nel programma proposto dall'autore del libro, si utilizza un dizionario con i valori già presenti, o, ad ogni chiamata ricorsiva, si fa la somma e si aggiorna il dizionario?
Peccato che non possa fare dei test, perché, come abbiamo visto, la versione ricorsiva, sulla mia macchina, esaurisce lo stack per valori >= 1000.
Di python ho solo qualche nozione base quindi non ne posso essere sicuro al 100% pero ad ogni volta che un numero non è presente nel dizionario viene calcolato il valore e poi viene aggiunto. La prima volta che si esegue una Fibonacci(1000) ci metterà un bel po' di tempo ma tutte le successive chiamate alla funzione con n <= 1000 saranno O(1) mentre per valori maggiori la ricorsione si fermerà non appena verrà trovato un valore nel dizionario.
Vincenzo1968
07-11-2008, 16:02
Di python ho solo qualche nozione base quindi non ne posso essere sicuro al 100% pero ad ogni volta che un numero non è presente nel dizionario viene calcolato il valore e poi viene aggiunto. La prima volta che si esegue una Fibonacci(1000) ci metterà un bel po' di tempo ma tutte le successive chiamate alla funzione con n <= 1000 saranno O(1) mentre per valori maggiori la ricorsione si fermerà non appena verrà trovato un valore nel dizionario.
E lo dici a me? Io di python non ne so proprio niente: proprio il niente che è niente.
Dando un'occhiata al codice proposto nel libro:
Precedenti = {0:1, 1:1}
def Fibonacci (n):
if Precedenti.has_key(n):
return Precedenti[n]
else:
NuovoValore = Fibonacci(n-1) + Fibonacci(n-2)
Precedenti [n] = NuovoValore
return NuovoValore
print Fibonacci(900)
si direbbe che il dizionario venga inizializzato soltanto con i primi due termini della successione di Fibonacci. In seguito, ad ogni chiamata ricorsiva, viene calcolato, effettuando la somma, il termine successivo e viene aggiunto al dizionario. E, comunque, si potrebbe utilizzare un dizionare anche con la versione iterativa, in modo che, dopo la prima volta, il tempo di ricerca sia O(1). O no?
Ho fatto una piccola prova ed in effetti finisco lo stack anche qui su osx. In ogni caso per raggiungere 1000 basta andare a piccoli passi.
cache = {0:0, 1:1}
def fib(n):
if cache.has_key(n):
return cache[n]
else:
cache[n] = fib(n-1) + fib(n-2)
return cache[n]
print fib(500)
print fib(1000)
print fib(1500)
print fib(2000)
Vincenzo1968
07-11-2008, 16:37
Versione iterativa con dizionario:
Precedenti = {0:1, 1:1, 2:1}
def Fibonacci (n):
if n < 1:
print "Che cacchio fai? n dev'essere >= 1."
return 0
if n <= 2:
return 1
if Precedenti.has_key(n):
return Precedenti[n]
a = 1
b = 1
Temp = 3
while Temp <= n:
Precedenti[Temp] = a + b
a = b
b = Precedenti[Temp]
Temp += 1
return Precedenti[Temp - 1]
print Fibonacci(1000)
print Fibonacci(10)
~FullSyst3m~
07-11-2008, 18:45
Versione iterativa con dizionario:
Precedenti = {0:1, 1:1, 2:1}
def Fibonacci (n):
if n < 1:
print "Che cacchio fai? n dev'essere >= 1."
return 0
if n <= 2:
return 1
if Precedenti.has_key(n):
return Precedenti[n]
a = 1
b = 1
Temp = 3
while Temp <= n:
Precedenti[Temp] = a + b
a = b
b = Precedenti[Temp]
Temp += 1
return Precedenti[Temp - 1]
print Fibonacci(1000)
print Fibonacci(10)
Il codice del libro, come è spiegato pure sotto, viene calcolato il nuovo valore e poi aggiunto il dizionario. Vincenzo1968 se non conosci Python, come lo scrivi il codice? Inoltre, perchè Precedenti[Temp - 1]?
Comunque, ho provato a rifare la stessa procedura con carta e penna su Fibonacci ricorsivo, ma siccome si chiama due volte ad ogni ciclo mi fa confondere. Inoltre non capisco molto questa formula, è molto più chiaro scritto in modo iterativo
P.S: nel capitolo 10.6, anche se ormai il problema degli interi lunghi non si pone più, la L viene messa nel dizionario, perché? Non dovrebbe essere messa nei numeri da calcolare?
~FullSyst3m~
07-11-2008, 18:52
Di python ho solo qualche nozione base quindi non ne posso essere sicuro al 100% pero ad ogni volta che un numero non è presente nel dizionario viene calcolato il valore e poi viene aggiunto. La prima volta che si esegue una Fibonacci(1000) ci metterà un bel po' di tempo ma tutte le successive chiamate alla funzione con n <= 1000 saranno O(1) mentre per valori maggiori la ricorsione si fermerà non appena verrà trovato un valore nel dizionario.
Cosa è O(1)? Comunque la funzione non si ferma per valori maggiori se avrà trovato un valore nel dizionario, ma calcolerà quei valori e li aggiungerà al dizionario. Quindi se calcoliamo Fibonacci (1000), prima aggiungerà i valori che non ci sono, e poi se chiameremo Fibonacci con n <= 1000 allora prenderà i valori nel dizionario e si fermerà subito. Quindi la velocità id calcolo è notevole
cdimauro
07-11-2008, 20:27
Non dai nulla di scontato, quello che hai scritto è scritto pure sul libro. Quello che dico è che se n = 1, allora FattorialeMenoUno = 0. Anche se poi 0 vale 1, sul libro hanno scritto 1 sicuramente per questo.
FattorialeMenoUno non vale mai zero, ma 1 quando si esegue Fattoriale(n - 1) per n = 1.
Quindi l'1 che viene moltiplicato ad n = 1 non è quello del return, ma quell di n = 0 che corrisponde ad 1?
E' quello di Fattoriale(n - 1), con n = 0.
Comunque le chiamate fin quando n != 0 rimangono ferme a FattorialeMenoUno e poi quando n = 0 fanno i vari calcoli di n con Risultato. Correggetemi se sbaglio ;)
Sì. Si arriva fino a FattorialeMenoUno = Fattoriale(n - 1) per n = 1. Nel momento in cui viene eseguita questa istruzione, si entra in Fattoriale per l'ultima volta, perché poi si ha immediatamente il valore (che è 1) e si torna su per completare le altre operazioni. E così via.
Uh quante certezze che hai! Come te le invidio :cool:
Che ci vuoi fare: è uno sporco lavoro, e qualcuno dovrà pur farlo. :O
La prima certezza è che io NON sono un buon informatico. Ma questa non è una novità. Non è la prima volta che me lo dici e io non ho mai affermato di essere un buon informatico e, anzi, ho sempre detto il contrario.
Va bene.
In quanto alle prestazioni, parlando dell'esempio riportato nel libro su Fibonacci, ho semplicemente rilevato che non mi pare azzeccato. È l'autore a parlare di prestazioni:
Come vedi, l'autore dà come buona soluzione, relativamente alle prestazioni, la versione ricorsiva con dizionario. Il che è una gran cazzata.
Continuo a pensare che avrebbe dovuto usare, per illustrare il funzionamento dei dizionari, qualunque altra cosa, non certo Fibonacci. :)
Certo, perché giustamente in un capitolo dedicato ai dizionari di cosa avrebbe dovuto parlare? Di tutto, fuorché dei dizionari:
Chapter 10
Dizionari
I tipi di dati composti che abbiamo visto finora (stringhe, liste e tuple) usano gli interi come indici. Qualsiasi tentativo di usare altri tipi di dati produce un errore.
I dizionari sono simili agli altri tipi composti ma si differenziano per il fatto di poter usare qualsiasi tipo di dato immutabile come indice.
:rolleyes:
Qui ha semplicemente fatto un esempio di calcolo del fattoriale facendo uso dei dizionari per velocizzarne l'esecuzione. Lo scopo NON era quello di calcolare i fattoriali nel modo più veloce possibile, ma nel prendere un soluzione già esistente ma inefficiente e trovare una soluzione algoritmica, basata sui dizionari, che consentisse di migliorare le prestazioni.
In nessuna parte del testo c'è scritto che l'obiettivo è di trovare la soluzione più performante.
Poi PER TE sarà pure una gran cazzata, ma intanto è perfettamente attinente allo scopo, e in secondo luogo il concetto di caching delle informazioni non è affatto una cazzata, visto che in informatica viene usato estensivamente, e questo ne è un chiaro esempio.
Di python ho solo qualche nozione base quindi non ne posso essere sicuro al 100% pero ad ogni volta che un numero non è presente nel dizionario viene calcolato il valore e poi viene aggiunto. La prima volta che si esegue una Fibonacci(1000) ci metterà un bel po' di tempo ma tutte le successive chiamate alla funzione con n <= 1000 saranno O(1) mentre per valori maggiori la ricorsione si fermerà non appena verrà trovato un valore nel dizionario.
Esattamente.
Poi è una soluzione molto pratica e veloce, specialmente se si deve utilizzare l'algoritmo più volte.
Ho fatto una piccola prova ed in effetti finisco lo stack anche qui su osx. In ogni caso per raggiungere 1000 basta andare a piccoli passi.
cache = {0:0, 1:1}
def fib(n):
if cache.has_key(n):
return cache[n]
else:
cache[n] = fib(n-1) + fib(n-2)
return cache[n]
print fib(500)
print fib(1000)
print fib(1500)
print fib(2000)
import sys
sys.setrecursionlimit(10000)
cache = {0:0, 1:1}
def fib(n):
if cache.has_key(n):
return cache[n]
else:
cache[n] = fib(n-1) + fib(n-2)
return cache[n]
fib(1000)
:cool:
P.S: nel capitolo 10.6, anche se ormai il problema degli interi lunghi non si pone più, la L viene messa nel dizionario, perché? Non dovrebbe essere messa nei numeri da calcolare?
Perché Python passa automaticamente gli interi agli interi lunghi quando il risultato di un'operazione non può essere rappresentato con un intero.
Per indicare che un numero è un intero lungo viene aggiunta la L alla sua fine.
Con Python 3.0 non ci saranno più differenze fra interi e interi lunghi: ci saranno soltanto gli interi e saranno già lunghi. :cool:
Cosa è O(1)?
E' una notazione per indicare la complessità di un algoritmo. O(1) indica che la complessità è costante.
Comunque la funzione non si ferma per valori maggiori se avrà trovato un valore nel dizionario, ma calcolerà quei valori e li aggiungerà al dizionario. Quindi se calcoliamo Fibonacci (1000), prima aggiungerà i valori che non ci sono, e poi se chiameremo Fibonacci con n <= 1000 allora prenderà i valori nel dizionario e si fermerà subito. Quindi la velocità id calcolo è notevole
Esattamente.
cdimauro
07-11-2008, 20:50
def fib(n)
return n if (0..1).include? n
fib(n-2) + fib(n-1)
end
def fib_i(n)
curr, succ = 0, 1
n.times do
curr, succ = succ, curr + succ
end
curr
end
def fact(n)
return 1 if n == 0
n * fact(n-1)
end
def fact_i(n)
f = 1
1.upto n do |i|
f *= i
end
f
end
puts fib(10)
puts fib_i(10)
puts fact(10)
puts fact_i(10)
Versione Python:
def fib(n):
return n if n <= 1 else fib(n - 2) + fib(n - 1)
def fib_i(n):
curr, succ = 0, 1
for i in xrange(n):
curr, succ = succ, curr + succ
return curr
def fact(n):
return n * fact(n - 1) if n else 1
def fact_i(n):
f = 1
for i in xrange(2, n + 1):
f *= i
return f
print fib(10)
print fib_i(10)
print fact(10)
print fact_i(10)
Mi sembra sia abbastanza compatto anche Python. :cool:
Vincenzo1968
07-11-2008, 21:22
in quel modo non esaurisci la memoria, ma solo lo stack, che mi pare cosa ben diversa...
Se controlli l'heap in quel momento trovi una marea di spazio...
Il problema è, piuttosto, che le chiamate ricorsive occupano spazio nello stack anzichè nell'heap.
E che comunque sono meno efficienti per un applicazione reale (e non didattica come questa :p)
P.S. che hanno fatto ad anno zero che io sono scappato quasi subito? :fagiano:
http://www.bastardidentro.it/misc/bastardidentro/data/images//b/bd1334-incontro-atteso1226051050.jpg
:D
~FullSyst3m~
07-11-2008, 21:34
FattorialeMenoUno non vale mai zero, ma 1 quando si esegue Fattoriale(n - 1) per n = 1.
Quello che volevo dire io
E' quello di Fattoriale(n - 1), con n = 0.
Con n = 0 non dovrebbe uscire la funzione?
Sì. Si arriva fino a FattorialeMenoUno = Fattoriale(n - 1) per n = 1. Nel momento in cui viene eseguita questa istruzione, si entra in Fattoriale per l'ultima volta, perché poi si ha immediatamente il valore (che è 1) e si torna su per completare le altre operazioni. E così via.
E questo valore 1 da dove viene "preso"? Dal return o da n = 0?
Perché Python passa automaticamente gli interi agli interi lunghi quando il risultato di un'operazione non può essere rappresentato con un intero.
Per indicare che un numero è un intero lungo viene aggiunta la L alla sua fine.
Con Python 3.0 non ci saranno più differenze fra interi e interi lunghi: ci saranno soltanto gli interi e saranno già lunghi. :cool:
Lo so che viene aggiunta la L, ma perchè viene aggiunta nel dizionario e non nel valore da calcolare?
def fib(n):
return n if n <= 1 else fib(n - 2) + fib(n - 1)
def fib_i(n):
curr, succ = 0, 1
for i in xrange(n):
curr, succ = succ, curr + succ
return curr
def fact(n):
return n * fact(n - 1) if n else 1
def fact_i(n):
f = 1
for i in xrange(2, n + 1):
f *= i
return f
print fib(10)
print fib_i(10)
print fact(10)
print fact_i(10)
Non sapevo si potesse usare questa sintassi, è vecchiotto sto libro che sto studiando uff.
Che significa xrange? E perchè xrange(2, n +1)?
cdimauro
07-11-2008, 21:44
Quello che volevo dire io
Con n = 0 non dovrebbe uscire la funzione?
Sì
E questo valore 1 da dove viene "preso"? Dal return o da n = 0?
Ovviamente dal return: è il return che "ritorna" qualcosa.
Lo so che viene aggiunta la L, ma perchè viene aggiunta nel dizionario e non nel valore da calcolare?
Che vuoi dire esattamente?
Non sapevo si potesse usare questa sintassi, è vecchiotto sto libro che sto studiando uff.
Sì, è vecchiotto, ma nasce per formarti la mente da programmatore e va benissimo allo scopo.
Avrai tutto il tempo per assaggiare le delizie delle versioni successive di Python. :cool:
Che significa xrange? E perchè xrange(2, n +1)?
xrange è uguale a range, ma ritorna un iteratore anziché una lista di interi. In questo modo si risparmia memoria perché non viene generata una lista con tutti i valori, ma questi vengono man mano calcolati uno alla volta.
xrange(2, n + 1) significa: ritorna tutti i numeri >= 2 e < n +1 (che poi equivale a <= n). ;)
~FullSyst3m~
07-11-2008, 22:06
Ovviamente dal return: è il return che "ritorna" qualcosa.
Questo vuol dire allora che quando n = 0 la funzione ritorna 1 ed esce. E poi da quell'1 inizia il calcolo di Risultato "all'indietro" cioè 1 * n =1, 1 * n=2, 2 * n=3?
Che vuoi dire esattamente?
Che non capisco perchè L è stata messa nel dizionario. Oltretutto dopo c'è un esercizio che chiede di modificare Fattoriale, ma come?
Sì, è vecchiotto, ma nasce per formarti la mente da programmatore e va benissimo allo scopo.
Avrai tutto il tempo per assaggiare le delizie delle versioni successive di Python. :cool:
Io voglio imparare, ho fretta. Devo recuperare tutti gli anni persi. :muro:
xrange è uguale a range, ma ritorna un iteratore anziché una lista di interi. In questo modo si risparmia memoria perché non viene generata una lista con tutti i valori, ma questi vengono man mano calcolati uno alla volta.
xrange(2, n + 1) significa: ritorna tutti i numeri >= 2 e < n +1 (che poi equivale a <= n). ;)
Sarebbe una specie di for e in? Comunque xrange(2, n+1) non dovrebbe significare pure da 2 incluso ad n+1 escluso?
P.S: perchè hai messo n+1?
cdimauro
07-11-2008, 22:19
Questo vuol dire allora che quando n = 0 la funzione ritorna 1 ed esce. E poi da quell'1 inizia il calcolo di Risultato "all'indietro" cioè 1 * n =1, 1 * n=2, 2 * n=3?
Esattamente! :)
Che non capisco perchè L è stata messa nel dizionario. Oltretutto dopo c'è un esercizio che chiede di modificare Fattoriale, ma come?
La L non è finita nel dizionario. Semplicemente quando viene stampato un qualunque intero lungo, viene sempre visualizzata la L alla sua fine.
Esempio:
>>> 1000000000000
1000000000000L
Ho scritto 1000000000000 ma quando viene stampato viene riportata la L alla fine.
Non ti preoccupare di questi dettagli: con le ultime versioni di Python non devi preoccuparti di interi e interi lunghi perché è tutto automatico. :cool:
Io voglio imparare, ho fretta. Devo recuperare tutti gli anni persi. :muro:
Non avere fretta perché non ti serve per aiutarti a migliorare le tue basi. Concentrati soltanto sullo studio, e le conclusioni tirale alla fine.
xrange è uguale a range, ma ritorna un iteratore anziché una lista di interi. In questo modo si risparmia memoria perché non viene generata una lista con tutti i valori, ma questi vengono man mano calcolati uno alla volta.
xrange(2, n + 1) significa: ritorna tutti i numeri >= 2 e < n +1 (che poi equivale a <= n). ;)
Sarebbe una specie di for e in?
No. Vedila come una lista "ottimizzata" per l'occupazione di memoria.
Una lista ha un certo numero di elementi, che però sono tutti presenti fisicamente in memoria. Una iteratore può restituirti tutti i numeri, ma soltanto uno alla volta, perché ogni numero viene calcolato al momento del bisogno.
Comunque lascia perdere per adesso: è un argomento più avanzato che tratterai più avanti.
Comunque xrange(2, n+1) non dovrebbe significare pure da 2 incluso ad n+1 escluso?
Esattamente.
P.S: perchè hai messo n+1?
Perché mi serve anche n. Se mettevo xrange(2, n), n veniva escluso.
~FullSyst3m~
08-11-2008, 07:44
Esattamente! :)
:)
La L non è finita nel dizionario. Semplicemente quando viene stampato un qualunque intero lungo, viene sempre visualizzata la L alla sua fine.
Quando dico che è finita nel dizionario intendo che l'hanno messa nel dizionario, cioè hanno modificato il codice e hanno messo la L nel dizionario. Guarda il libro e capirai meglio
Non avere fretta perché non ti serve per aiutarti a migliorare le tue basi. Concentrati soltanto sullo studio, e le conclusioni tirale alla fine.
E che ho perso troppi anni :muro: Mi concentro solo sullo studio comunque
No. Vedila come una lista "ottimizzata" per l'occupazione di memoria.
Una lista ha un certo numero di elementi, che però sono tutti presenti fisicamente in memoria. Una iteratore può restituirti tutti i numeri, ma soltanto uno alla volta, perché ogni numero viene calcolato al momento del bisogno.
Comunque lascia perdere per adesso: è un argomento più avanzato che tratterai più avanti.
No, io intendevo che è simile perchè attraversa una lista, anche se in modo diverso
Esattamente.
;)
Perché mi serve anche n. Se mettevo xrange(2, n), n veniva escluso.
Che scemo, è vero. Dato che n sarebbe escluso, con +1 lo include :D
P.S: solo due chiarimenti mi servono per poter andare avanti, non voglio andare avanti se non mi tolgo i dubbi. La funzione ricorsiva di Fibonacci (che anche se ho provato a fare con lo stesso procedimento di Fattoriale su carta e penna non mi torna perchè si chiama due volte) e il fatto dei return scritto qualche post più sopra
cdimauro
08-11-2008, 08:01
Quando dico che è finita nel dizionario intendo che l'hanno messa nel dizionario, cioè hanno modificato il codice e hanno messo la L nel dizionario. Guarda il libro e capirai meglio
Se ti riferisci a questo:
Precedenti = {0:1L, 1:1L}
è normale che ci sia finito, perché nelle versioni più vecchie di Python se volevi usare gli interi lunghi dovevi appendere la L alla fine del numero.
E che ho perso troppi anni :muro: Mi concentro solo sullo studio comunque
Fai bene, perché i risultati arrivano, come puoi ben vedere. :)
No, io intendevo che è simile perchè attraversa una lista, anche se in modo diverso
Attenzione: le liste si "attraversano" usando l'istruzione for. Da questo punto di vista liste e iteratori (e generatori; entrambi li vedrai più avanti, per cui NON ti curar di loro adesso) si comportano esattamente allo stesso modo. Ma, a parte questi casi, si tratta di oggetti diversi che si comportano in maniera diversa.
P.S: solo due chiarimenti mi servono per poter andare avanti, non voglio andare avanti se non mi tolgo i dubbi. La funzione ricorsiva di Fibonacci (che anche se ho provato a fare con lo stesso procedimento di Fattoriale su carta e penna non mi torna perchè si chiama due volte)
Sì, ti capisco. E' più complicata appunto perché viene richiamata 2 volte, ma concettualmente è la stessa cosa. Devi considerare che, come al solito, appena c'è da eseguire la prima invocazione a Fibonacci lo stato corrente della funzione viene congelato, e si procede al solito modo ("scendendo" fino a che non si arriva a n = 0 oppure n = 1), successivamente si risale, ma poi c'è da eseguire la seconda invocazione alla funzione, per cui si ricomincia nuovamente a "scendere".
Comunque se guardi il libro c'è il grafico delle chiamate che ti può aiutare a capire come funziona.
e il fatto dei return scritto qualche post più sopra
Riportalo perché mi sono perso. Vedo di risponderti stasera, se ho tempo, perché sto uscendo con la famiglia.
Per il PVT: tranquillo! I conti facciamoli alla fine. Abbi fiducia. :)
~FullSyst3m~
08-11-2008, 08:15
Se ti riferisci a questo:
Precedenti = {0:1L, 1:1L}
è normale che ci sia finito, perché nelle versioni più vecchie di Python se volevi usare gli interi lunghi dovevi appendere la L alla fine del numero.
Si mi riferisco a questo e so che la L si deve mettere alla fine del numero, quello che voglio dire è: perchè messa proprio nel dizionario?
Fai bene, perché i risultati arrivano, come puoi ben vedere. :)
Tutto vedo tranne che risultati, dovrei essere molto più avanti e sono fermo sulle cose basilari e banali :muro: :muro:
Attenzione: le liste si "attraversano" usando l'istruzione for. Da questo punto di vista liste e iteratori (e generatori; entrambi li vedrai più avanti, per cui NON ti curar di loro adesso) si comportano esattamente allo stesso modo. Ma, a parte questi casi, si tratta di oggetti diversi che si comportano in maniera diversa.
Ok, grazie per la spiegazione
Sì, ti capisco. E' più complicata appunto perché viene richiamata 2 volte, ma concettualmente è la stessa cosa. Devi considerare che, come al solito, appena c'è da eseguire la prima invocazione a Fibonacci lo stato corrente della funzione viene congelato, e si procede al solito modo ("scendendo" fino a che non si arriva a n = 0 oppure n = 1), successivamente si risale, ma poi c'è da eseguire la seconda invocazione alla funzione, per cui si ricomincia nuovamente a "scendere".
Comunque se guardi il libro c'è il grafico delle chiamate che ti può aiutare a capire come funziona.
Concettualmente si, ma viene chiamata due volte. Se ad esempio inizio a chiamarla con n = 4, poi viene richiamata con n = 3 e n = 2. Il punto è che ora abbiamo "due" n, mentre viene eseguita la prima (n=3), la seconda resta in attesa che finisca la prima?
Riportalo perché mi sono perso. Vedo di risponderti stasera, se ho tempo, perché sto uscendo con la famiglia.
Eccolo il link del messaggio (ci sono anche le altre cose di cui stavamo parlando e che poi abbiamo lasciato a metà): http://www.hwupgrade.it/forum/showpost.php?p=24889767&postcount=262
Per il PVT: tranquillo! I conti facciamoli alla fine. Abbi fiducia. :)
Sarà il linguaggio o sarà qualcos'altro, ma tu pensi che sia normale perdere tutto questo tempo per capire delle cose cosi banali? Comunque ho fiducia (anche se non so perchè) altrimenti non sarei qua ;)
P.S: buona uscita :D
Sarà il linguaggio o sarà qualcos'altro, ma tu pensi che sia normale perdere tutto questo tempo per capire delle cose cosi banali? Comunque ho fiducia (anche se non so perchè) altrimenti non sarei qua ;)
Ciao, ti rispondo solo su questa cosa.
Io studio Infomatica all'Università di Bologna e ti posso assicurare che la ricorsione non è banale ne all'inizio ne (a volte) dopo. E' uno scoglio molto duro da superare per chi inizia a programmare che necessita di molta pratica.
Ciao.
~FullSyst3m~
08-11-2008, 14:07
Ciao, ti rispondo solo su questa cosa.
Io studio Infomatica all'Università di Bologna e ti posso assicurare che la ricorsione non è banale ne all'inizio ne (a volte) dopo. E' uno scoglio molto duro da superare per chi inizia a programmare che necessita di molta pratica.
Ciao.
Ciao e grazie per essere intervenuto nella mia discussione. Sono restato un pò sorpreso di sentire dire questa cosa, sopratutto da uno studente universitario, e dovrebbe un pò farmi riflettere. Ma sono sempre dell'idea che non è normale che perdere tutto questo tempo per imparare queste cose (mi riferisco a tutti i capitoli del libro studiati fino ad ora, non solo alla ricorsione)
cdimauro
08-11-2008, 20:50
Si mi riferisco a questo e so che la L si deve mettere alla fine del numero, quello che voglio dire è: perchè messa proprio nel dizionario?
Per specificare che i numeri sono interi lunghi, appunto.
Comunque non te ne curare: evita pure di mettere la L alla fine, perché da un bel pezzo Python converte automaticamente gli interi in interi lunghi appena si rende necessario. :cool:
Tutto vedo tranne che risultati, dovrei essere molto più avanti e sono fermo sulle cose basilari e banali :muro: :muro:
Vedremo, vedremo. ;)
Concettualmente si, ma viene chiamata due volte. Se ad esempio inizio a chiamarla con n = 4, poi viene richiamata con n = 3 e n = 2. Il punto è che ora abbiamo "due" n, mentre viene eseguita la prima (n=3), la seconda resta in attesa che finisca la prima?
Esattamente! :)
Eccolo il link del messaggio (ci sono anche le altre cose di cui stavamo parlando e che poi abbiamo lasciato a metà): http://www.hwupgrade.it/forum/showpost.php?p=24889767&postcount=262
OK
Sarà il linguaggio o sarà qualcos'altro, ma tu pensi che sia normale perdere tutto questo tempo per capire delle cose cosi banali? Comunque ho fiducia (anche se non so perchè) altrimenti non sarei qua ;)
P.S: buona uscita :D
Grazie. :)
Come vedi il concetto di ricorsione non è semplice, e ti mancano pure delle basi di matematica, ma nonostante tutto sei vicino alla comprensione del concetto. ;)
cdimauro
08-11-2008, 21:06
Non vedo nessuna differenza tra questo codice e quello senza parametri
Alla fine ho aggiunto il parametro ', ' che rappresenta la stringa da usare per suddividere le stringhe.
Si lo ricordo quel messaggio. Allora, sono tornato indietro di qualche capitolo per ripassare meglio la ricorsione, e come esempio (visto che era nominato nel paragrafo degli interi lunghi) ho preso la funzione Fattoriale. Ecco il codice:
def Fattoriale (n):
if n == 0:
return 1
else:
FattorialeMenoUno = Fattoriale (n-1)
Risultato = n * FattorialeMenoUno
return Risultato
Scrivendo il fattoriale di un numero su carta e penna ho capito il procedimento, che di per sè è molto semplice, e anche simulando il funzionamento del codice su carta e penna non ho avuto nessun problema. Ho avuto la conferma che la ricorsione l'ho capita, le due cose che però non mi tornano (e che probabilmente non mi fanno quadrare nemmeno Fibonacci):
mettiamo caso che chiamo Fattoriale con n = 3. Siccome n != 0 si esegue il ramo dell'else. La prima istruzione ad essere eseguita è FattorialeMenoUno = Fattoriale (n-1). Allora, arrivati a questo punto n è uguale a 3 e Fattoriale viene richiamato con n = 2, quindi Risultato non viene eseguito.
No, infatti: bisogna aspettare il ritorno dalla chiamata a Fattoriale(n - 1).
Visto che n è ancora diverso da 0 si rifà la stessa procedura, ma ora abbiamo n = 1 e cosi via fino a quanto n non è uguale a 0. Ora, quando n = 0 abbiamo le variabili "congelate" (cit.:asd:) n = 3, n = 2 e n = 1 giusto? Quello che mi chiedo è:
Risultato quando viene eseguito? E quando viene eseguito, n e FattorialeMenoUno che valore hanno?
Risultato viene eseguito nel momento in cui Fattoriale(0) ritorna (con 1). Adesso può finalmente calcolare n * FattorialeMenoUno, cioé 1 * 1 = 1 e metterlo in Risultato, per poi chiudere questa chiamata e tornare il valore calcolato a chi, a sua volta, aveva chiamato Fattoriale con n = 1.
Il return serve proprio a prendere 1 e a tornarlo al chiamante, cioé Fattoriale(2) che lo prenderà e calcolerà a sua volta n * FattorialeMenoUno, che in questo caso corrisponde a 2 * 1. E così via risalendo.
Quando n = 0 viene eseguito l'if e la funzione dovrebbe terminare, invece continua a fare i suoi conti.
No, perché l'if torna immediamente sù col valore 1. Quindi la chiamata alla funzione termina subito.
Infine, quel return, come nel caso di Fibonacci, se viene tolto dà il famoso errore. Ho capito il perchè, come ha spiegato VICIUS, però non capisco come ragiona l'interprete visto che il return è alla fine e non all'inizio. Questo significa che return dovrebbe tornare il valore finale, quando cioè l'ooperazione è già stata conclusa.
Esattamente. A questo Risultato contiene il valore (finalmente) calcolato e può tornarlo al chiamante.
Quindi perchè se metto il print al posto del return mi dà errore??
Semplice: perché return torna il valore intero calcolato al chiamante che... si aspetta, appunto, un valore intero.
Se non metti il return Python all'uscita dalla funzione ritorna None al chiamante, che proverà a moltiplicarlo con la sua n, e... darà errore.
Quindi mettendoci il print otterresti la stampa di 1 a video, ma poi l'applicazione solleverebbe un'eccezione, visto che cercando di calcolare n * FattorialeMenoUno si troverebbe a dover effettuare 2 * None.
Sono banali queste domande per voi, lo so. Però se studiassi solo sul libro capirei tutto, però mi chiedo un sacco di cose, poi provo... e spuntano le domande! :D
E arrivano anche le risposte, appena c'è la possibilità di farlo. :)
Uno? Nel libro c'è messo che si dovrebbe passare chiave e valore che si vuole tornare.
Il libro dice questo:
"Il primo argomento è la tupla-chiave, il secondo il valore che get deve ritornare nel caso la chiave non sia presente nel dizionario"
che è esattamente ciò che ho scritto prima. :)
get serve, data la chiave, per tornare il valore corrispondente se la chiave viene trovata, altrimenti (quindi chiave non trovata) torna il valore che tu hai passato come secondo argomento.
Inoltre in quel caso (parlo per quel programmino) credo che il get serva per incrementare il conteggio. O no?.
Mi son perso il programmino di cui parli. :(
Comunque Dizionario[Chiave] serve per creare la chiave o per vedere il valore appartenente alla chiave.
Sì, se usato come assegnazione o come lettura rispettivamente.
Nella shell di pyscript e di python in ufficio mi dava un errore (non ricordo quale al momento), nella pyshell su linux invece no :D
Non uso PyScript, per cui non so.
Ad esempio Fibonacci (12121212
1212) oppure ["ciao", "prova",
"tre"] sono validi?
Qui mi son perso un pezzo: cosa volevi dire?
~FullSyst3m~
08-11-2008, 23:41
Per specificare che i numeri sono interi lunghi, appunto.
Comunque non te ne curare: evita pure di mettere la L alla fine, perché da un bel pezzo Python converte automaticamente gli interi in interi lunghi appena si rende necessario. :cool:
Non mi spiego :muro: Questo lo so, dico solo: perchè la L nel dizionario? Cioè, il dizionario non viene usato "per il calcolo". Non so se hai capito che voglio dire...
Vedremo, vedremo. ;)
Vedremo, vedremo...
Esattamente! :)
Quindi n = 3 viene eseguita finchè n = 0 e poi n = 2 (che era la variabile "congelata" di Fibonacci (n-2) con Fibonacci (4)) viene eseguita finchè non arriva a 0. Giusto?
Come vedi il concetto di ricorsione non è semplice, e ti mancano pure delle basi di matematica, ma nonostante tutto sei vicino alla comprensione del concetto. ;)
Non mi sembra di aver fatto nulla di straordinario, anzi tutto il contrario
~FullSyst3m~
08-11-2008, 23:57
Alla fine ho aggiunto il parametro ', ' che rappresenta la stringa da usare per suddividere le stringhe.
Io ho provato a mettere - al posto della virgola ma vengono separati sempre con la virgola
No, perché l'if torna immediamente sù col valore 1. Quindi la chiamata alla funzione termina subito.
Che vuoi dire? Comunque io Fattoriale l'ho capito, però non capisco perchè il return 1 dell'if invece di terminare la funzione e uscire passa l'1 per poter iniziare a fare i calcoli. Quel return dovrebbe significare che quando n = 0 dovrebbe ritornare 1 e uscire...
Se non metti il return Python all'uscita dalla funzione ritorna None al chiamante, che proverà a moltiplicarlo con la sua n, e... darà errore.
Scusa, stiamo parlando di Risultato? Perchp risultato dovrebbe tornare solo il risultato, non il FattorialeMenoUno che va moltiplicato ad n. Il FattorialeMenoUno è già stato calcolato nei cicli precedenti
Quindi mettendoci il print otterresti la stampa di 1 a video, ma poi l'applicazione solleverebbe un'eccezione, visto che cercando di calcolare n * FattorialeMenoUno si troverebbe a dover effettuare 2 * None.
Per quale valore di n stai parlando?
E arrivano anche le risposte, appena c'è la possibilità di farlo. :)
Forse mi faccio troppe domande...
get serve, data la chiave, per tornare il valore corrispondente se la chiave viene trovata, altrimenti (quindi chiave non trovata) torna il valore che tu hai passato come secondo argomento.
Scusa, ma per tornare il valore non basta chiamare il dizionario con la chiave tra parentesi quadre (Dizionario['one'] = 'uno')? Non credo che ci sia bisogno di get. get dovrebbe essere usato esclusivamente se la chiave non è presente in modo da poter tornare il valore che si vuole
Mi son perso il programmino di cui parli. :(
ConteggioLettere = {}
>>> for Lettera in "Mississippi":
... ConteggioLettere [Lettera] = ConteggioLettere.get \
... (Lettera, 0) + 1
Sì, se usato come assegnazione o come lettura rispettivamente.
Bene ;)
Qui mi son perso un pezzo: cosa volevi dire?
Mi riferivo a quello che avevi detto riguardo lo \: No, serve per specificare che un'istruzione sta andando a capo e quindi bisogna proseguire nella riga seguente.
Con Python un'istruzione normalmente finisce a fine riga, e si considera quindi "chiusa". Se è troppo lunga la si "spezza" in più righe tramite \ appunto.
Se invece si sta elencando qualcosa (ad esempio l'elenco di una lista, di un dizionario, o i parametri di una funzione), il carattere \ non è necessario quando si va a capo.
E io ti ho fatto l'esempio della chiamata di funzione e della lista per vedere se intendevi questo e se è corretto in quel modo:
Ad esempio Fibonacci (12121212
1212) oppure ["ciao", "prova",
"tre"] sono validi?
cdimauro
09-11-2008, 20:03
Non mi spiego :muro: Questo lo so, dico solo: perchè la L nel dizionario? Cioè, il dizionario non viene usato "per il calcolo". Non so se hai capito che voglio dire...
Il dizionario viene usato per il calcolo, e infatti memorizza i valori di Fibonacci man mano che vengono prodotti. Semplicemente all'inizio viene inizializzato con due calcoli già "belli e pronti" per semplificare il codice della funzione Fibonacci.
Quindi n = 3 viene eseguita finchè n = 0 e poi n = 2 (che era la variabile "congelata" di Fibonacci (n-2) con Fibonacci (4)) viene eseguita finchè non arriva a 0. Giusto?
Tutte le chiamate a Fibonacci devono arrivare a Fibonacci(0) o Fibonacci(1), e per queste chiamate sicuramente verrà restituito immediatamente il valore, perché è stato già caricato prima nel dizionario.
Non mi sembra di aver fatto nulla di straordinario, anzi tutto il contrario
OK, lasciamo perdere. Ne riparliamo a fine libro.
~FullSyst3m~
09-11-2008, 20:07
Il dizionario viene usato per il calcolo, e infatti memorizza i valori di Fibonacci man mano che vengono prodotti. Semplicemente all'inizio viene inizializzato con due calcoli già "belli e pronti" per semplificare il codice della funzione Fibonacci.
Non mi sono spiegato, questo lo so. Dico solo per la L è stata messa nel dizionario. Solo questo
Tutte le chiamate a Fibonacci devono arrivare a Fibonacci(0) o Fibonacci(1), e per queste chiamate sicuramente verrà restituito immediatamente il valore, perché è stato già caricato prima nel dizionario.
Quello che dico è che le due chiamate di funzioni vengono eseguite in "fila". Cioè, al'inizio abbiamo n = 4. Poi n = 3 e n = 2. Ora, n = 3 viene eseguito finche n = 1, dopodichè viene eseguito n = 2 finchè n = 1. Giusto?
OK, lasciamo perdere. Ne riparliamo a fine libro
Va bene
cdimauro
09-11-2008, 20:29
Io ho provato a mettere - al posto della virgola ma vengono separati sempre con la virgola
C'è, c'è. Guarda qui:
>>> import string
>>> string.split('Qui, Quo, Qua', ', ')
['Qui', 'Quo', 'Qua']
>>> string.split('Qui, Quo, Qua', '- ')
['Qui, Quo, Qua']
Che vuoi dire? Comunque io Fattoriale l'ho capito, però non capisco perchè il return 1 dell'if invece di terminare la funzione e uscire passa l'1 per poter iniziare a fare i calcoli. Quel return dovrebbe significare che quando n = 0 dovrebbe ritornare 1 e uscire...
Ma infatti esce da QUELLA invocazione di Fattoriale (con n = 0). Però uscendo da quella, dove ritorna Python? Al passo successivo a quello che stava facendo quando ha chiamato Fattoriale(0). Solo che ci torna col valore che ha preso dall'uscita di Fattoriale(0), che è 1. E lo impiega per continuare i calcoli.
Scusa, stiamo parlando di Risultato? Perchp risultato dovrebbe tornare solo il risultato, non il FattorialeMenoUno che va moltiplicato ad n. Il FattorialeMenoUno è già stato calcolato nei cicli precedenti
Non è stato calcolato se hai sostuito la print al return.
Prendiamo il codice per n = 1 e vediamo cosa succede. Siamo qui:
FattorialeMenoUno = Fattoriale (n-1)
Risultato = n * FattorialeMenoUno
print Risultato
Abbiamo detto che n = 1. A questo punto dobbiamo calcolare Fattoriale(n - 1). Vuol dire invocheremo Fattoriale(0), ma questo restituisce 1 perché il codice eseguito in questo caso è:
if n == 0:
return 1
A questo punto, uscendo da Fattoriale(0) abbiamo ottenuto il valore 1, che finisce in FattorialeMenoUno.
Quindi a questo punto avremo: n = 1 e FattorialeMenoUno = 1.
Adesso calcoliamo Risultato che è uguale a 1 * 1, cioé 1.
Bene, ultima cosa: lo stampiamo a video (e otteniamo 1 sullo schermo) e usciamo dalla funzione. Solo che stiamo uscendo SENZA SPECIFICARE ALCUN VALORE DA TORNARE, e in questo caso è come se Python eseguisse implicitamente un return None.
Cosa significa questo? Che Fattoriale(1) restituirà None a chi lo chiamerà.
E cosa succederà, allora, se calcoliamo Fattoriale(2)? Semplice: verrà eseguito il primo pezzo di codice che ho postato. Vediamo passo passo cosa succede.
Ricordiamo che n = 2. A questo avremo che FattorialeMenoUno = Fattoriale (n-1) sarà uguale a: FattorialeMenoUno = Fattoriale (1).
Ma sappiamo che Fattoriale(1) restituisce None (vedi sopra), quindi FattorialeMenoUno = None.
Proseguiamo col calcolo di Risultato = n * FattorialeMenoUno. In questo caso avremo Risultato = 2 * FattorialeMenoUno = 2 * None. E qui Python solleva un'eccezione perché non si può moltiplicare un numero per None.
E' chiaro adesso? Ripercorrendo passo passo l'esecuzione del codice dovremmo essere a posto. :)
Per quale valore di n stai parlando?
Scusami: n = 2 ovviamente. Vedi sopra. Finché abbiamo n = 1 o n = 0 Python non solleverà mai alcun errore.
Forse mi faccio troppe domande...
Se hai dubbi, è giusto che te le faccia. ;)
Scusa, ma per tornare il valore non basta chiamare il dizionario con la chiave tra parentesi quadre (Dizionario['one'] = 'uno')? Non credo che ci sia bisogno di get.
In QUESTO caso infatti non c'è bisogno.
get dovrebbe essere usato esclusivamente se la chiave non è presente in modo da poter tornare il valore che si vuole
ConteggioLettere = {}
>>> for Lettera in "Mississippi":
... ConteggioLettere [Lettera] = ConteggioLettere.get \
... (Lettera, 0) + 1
No, qui casca l'asino. get va usato esclusivamente se NON si vuol sollevare un'eccezione, ma questo soltanto quando Python non trova quella chiave nel dizionario.
Ricapitolando. Con get se Python trova la chiave nel dizionario, restituisce il valore corrispondente alla chiave. Altrimenti torna sempre quello che tu gli hai specificato come secondo parametro.
Ecco qui:
>>> Dizionario = {0 : 1, 1 : 1}
>>> Dizionario.get(0, 'Ciao!')
1
>>> Dizionario.get(12345, 'Ciao!')
'Ciao!'
Mi riferivo a quello che avevi detto riguardo lo \:
E io ti ho fatto l'esempio della chiamata di funzione e della lista per vedere se intendevi questo e se è corretto in quel modo:
Ad esempio Fibonacci (12121212
1212) oppure ["ciao", "prova",
"tre"] sono validi?
Il primo caso non è valido. Devi scrivere Fibonacci(121212121212). Il secondo è giusto.
cdimauro
09-11-2008, 20:36
Non mi sono spiegato, questo lo so. Dico solo per la L è stata messa nel dizionario. Solo questo
E' stata messa per specificare che i numeri siano interi lunghi. Ma ripeto: roba del passato, e non serve più. Mettici una pietra sopra. ;)
Quello che dico è che le due chiamate di funzioni vengono eseguite in "fila". Cioè, al'inizio abbiamo n = 4. Poi n = 3 e n = 2. Ora, n = 3 viene eseguito finche n = 1, dopodichè viene eseguito n = 2 finchè n = 1. Giusto?
Esattamente. :)
~FullSyst3m~
09-11-2008, 22:38
C'è, c'è. Guarda qui:
>>> import string
>>> string.split('Qui, Quo, Qua', ', ')
['Qui', 'Quo', 'Qua']
>>> string.split('Qui, Quo, Qua', '- ')
['Qui, Quo, Qua']
L'unica differenza che vedo è che al posto di esserci "tre" stringhe separate, è una stringa "unica". Il trattino però non lo vedo, vedo sempre la virgola
Ma infatti esce da QUELLA invocazione di Fattoriale (con n = 0). Però uscendo da quella, dove ritorna Python? Al passo successivo a quello che stava facendo quando ha chiamato Fattoriale(0). Solo che ci torna col valore che ha preso dall'uscita di Fattoriale(0), che è 1. E lo impiega per continuare i calcoli.
Non è stato calcolato se hai sostuito la print al return.
Prendiamo il codice per n = 1 e vediamo cosa succede. Siamo qui:
FattorialeMenoUno = Fattoriale (n-1)
Risultato = n * FattorialeMenoUno
print Risultato
Abbiamo detto che n = 1. A questo punto dobbiamo calcolare Fattoriale(n - 1). Vuol dire invocheremo Fattoriale(0), ma questo restituisce 1 perché il codice eseguito in questo caso è:
if n == 0:
return 1
A questo punto, uscendo da Fattoriale(0) abbiamo ottenuto il valore 1, che finisce in FattorialeMenoUno.
Quindi a questo punto avremo: n = 1 e FattorialeMenoUno = 1.
Adesso calcoliamo Risultato che è uguale a 1 * 1, cioé 1.
Bene, ultima cosa: lo stampiamo a video (e otteniamo 1 sullo schermo) e usciamo dalla funzione. Solo che stiamo uscendo SENZA SPECIFICARE ALCUN VALORE DA TORNARE, e in questo caso è come se Python eseguisse implicitamente un return None.
Cosa significa questo? Che Fattoriale(1) restituirà None a chi lo chiamerà.
E cosa succederà, allora, se calcoliamo Fattoriale(2)? Semplice: verrà eseguito il primo pezzo di codice che ho postato. Vediamo passo passo cosa succede.
Ricordiamo che n = 2. A questo avremo che FattorialeMenoUno = Fattoriale (n-1) sarà uguale a: FattorialeMenoUno = Fattoriale (1).
Ma sappiamo che Fattoriale(1) restituisce None (vedi sopra), quindi FattorialeMenoUno = None.
Proseguiamo col calcolo di Risultato = n * FattorialeMenoUno. In questo caso avremo Risultato = 2 * FattorialeMenoUno = 2 * None. E qui Python solleva un'eccezione perché non si può moltiplicare un numero per None.
E' chiaro adesso? Ripercorrendo passo passo l'esecuzione del codice dovremmo essere a posto. :)
Ehm... mi dispiace averti fatto perdere tempo, ma qualche minuto prima di uscire ho rifatto tutto su carta e ho scritto anche un diagramma di stato e ho capito il funzionamento, grazie lo stesso comunque... ho avuto conferma cosi :D
Se hai dubbi, è giusto che te le faccia. ;)
Non le faccio perchè ho dubbi, ma perchè ogni mi volta mi chiedo: "ma se ad esempio..."
No, qui casca l'asino. get va usato esclusivamente se NON si vuol sollevare un'eccezione, ma questo soltanto quando Python non trova quella chiave nel dizionario.
Ricapitolando. Con get se Python trova la chiave nel dizionario, restituisce il valore corrispondente alla chiave. Altrimenti torna sempre quello che tu gli hai specificato come secondo parametro.
Questo è spiegato chiarissimo nel libro, dico solo che se una chiave è nel dizionario non c'è bisogno di usare get
Il primo caso non è valido. Devi scrivere Fibonacci(121212121212). Il secondo è giusto.
Perchè non è valido? Avevi scritto che quando si sta elencanco una lista o un dizionario o i parametri di una funzione non c'è bisogno di \ per andare a capo, quindi dovrebbe essere valido Funzione (xxx, x
x)
P.S: se la lista è valida è valido anche questo allora:
dizionario = {'ciao': 'hello', 'buongiorno':
goodmorning}
~FullSyst3m~
09-11-2008, 22:42
E' stata messa per specificare che i numeri siano interi lunghi. Ma ripeto: roba del passato, e non serve più. Mettici una pietra sopra. ;)
Su questo siamo d'accordo che è messa per specificare che i numeri sono interi lunghi. Però mi chiedo: perchè nel dizionario? Non dovrebbe essere messa tipo nel parametro? Allora, visto che è cosi, la funzione Fattoriale ricorsiva come si dovrebbe modificare per convertire in interi lunghi i numeri? So che ormai il problema non si pone più, però voglio capire...
Esattamente. :)
Bene. L'ultima cosa per avere il quadro completo è quella che ti ho scritto nel pm, però non mi hai più risposto
DanieleC88
10-11-2008, 01:44
L'unica differenza che vedo è che al posto di esserci "tre" stringhe separate, è una stringa "unica". Il trattino però non lo vedo, vedo sempre la virgola
Non lo devi vedere, la stringa passata come argomento lì non viene inserita da nessuna parte, ma è ciò che tu dici a Python di interpretare come separatore di pezzi di una stringa.
Se io ho stringa = 'ciao sono una stringa' e separatore = ' ', allora stringa.split(separatore) ti restituirà una lista con 4 stringhe: ['ciao', 'sono', 'una', 'stringa']. Se invece fosse, ad esempio, separatore = '!' (che non compare mai), allora stringa.split(separatore) ti restituirebbe una lista con 1 stringa: ['ciao sono una stringa']. Vedi differenza? ;)
~FullSyst3m~
10-11-2008, 07:25
Non lo devi vedere, la stringa passata come argomento lì non viene inserita da nessuna parte, ma è ciò che tu dici a Python di interpretare come separatore di pezzi di una stringa.
Se io ho stringa = 'ciao sono una stringa' e separatore = ' ', allora stringa.split(separatore) ti restituirà una lista con 4 stringhe: ['ciao', 'sono', 'una', 'stringa']. Se invece fosse, ad esempio, separatore = '!' (che non compare mai), allora stringa.split(separatore) ti restituirebbe una lista con 1 stringa: ['ciao sono una stringa']. Vedi differenza? ;)
Si, vedo la stessa differenza dell'esempio di cdimauro, e cioè prima "quattro" stringhe e poi "una" stringa. Io pensavo che se si metteva ad esempio '-' allora il separatore doveva essere il trattino e veniva visualizzato. Come il join..
cdimauro
10-11-2008, 07:49
No, perché la join usa il trattino per unire le stringhe presenti in una lista, mentre la split fa l'esatto opposto: va a caccia del trattino per "dividere" la stringa in una lista di stringhe.
Sul resto rispondo quando ho tempo. :)
~FullSyst3m~
10-11-2008, 11:07
No, perché la join usa il trattino per unire le stringhe presenti in una lista, mentre la split fa l'esatto opposto: va a caccia del trattino per "dividere" la stringa in una lista di stringhe.
La join però se metto il trattino me le unisce con il trattino (ciao_come_stai_?), invece la split divide sempre con la virgola oppure se metto una lettera (come nell'esempio del libro) le divide con quelle. Però come hai fatto tu come delimitatore non lo vedo il trattino.
Sul resto rispondo quando ho tempo. :)
Ok ;)
cdimauro
10-11-2008, 12:56
L'unica differenza che vedo è che al posto di esserci "tre" stringhe separate, è una stringa "unica". Il trattino però non lo vedo, vedo sempre la virgola
Ho capito la fonte di tutti i problemi: la virgola. :D
Ecco qui:
>>> import string
>>> string.split('Qui+Quo+Qua', '+')
['Qui', 'Quo', 'Qua']
>>> string.split('Qui+Quo+Qua')
['Qui+Quo+Qua']
Con quest'esempio è più chiaro.
Ehm... mi dispiace averti fatto perdere tempo, ma qualche minuto prima di uscire ho rifatto tutto su carta e ho scritto anche un diagramma di stato e ho capito il funzionamento, grazie lo stesso comunque... ho avuto conferma cosi :D
Perfetto. :)
Non le faccio perchè ho dubbi, ma perchè ogni mi volta mi chiedo: "ma se ad esempio..."
Va bene lo stesso: se ti vengono in mente delle idee, esponile pure.
Questo è spiegato chiarissimo nel libro, dico solo che se una chiave è nel dizionario non c'è bisogno di usare get
Certamente, ma nel caso in questione la chiave potrebbe, appunto, non essere presente nel dizionario. In questo caso si usa la get.
Perchè non è valido? Avevi scritto che quando si sta elencanco una lista o un dizionario o i parametri di una funzione non c'è bisogno di \ per andare a capo, quindi dovrebbe essere valido Funzione (xxx, x
x)
No, in questo caso c'è un errore perché manca la virgola alla fine della riga. Dovresti scrivere così:
Funzione(xxx, x,
x)
P.S: se la lista è valida è valido anche questo allora:
dizionario = {'ciao': 'hello', 'buongiorno':
'goodmorning'}
Sì, funziona pure perché stai elencando gli elementi di un dizionario.
Su questo siamo d'accordo che è messa per specificare che i numeri sono interi lunghi. Però mi chiedo: perchè nel dizionario? Non dovrebbe essere messa tipo nel parametro?
In Python il tipo è definito dal valore stesso. Se scrivo 'Ciao' so che questo è un oggetto di tipo stringa. Se scrivo 123 so che questo è un intero. Se scrivo 123L so che questo è un intero lungo.
Quindi per forza di cose la L andava messa nei valori presenti nel dizionario.
Allora, visto che è cosi, la funzione Fattoriale ricorsiva come si dovrebbe modificare per convertire in interi lunghi i numeri? So che ormai il problema non si pone più, però voglio capire...
Basta appendere L alla fine di ogni intero che è presente in quella funzione.
Bene. L'ultima cosa per avere il quadro completo è quella che ti ho scritto nel pm, però non mi hai più risposto
Per favore, riportale qui. I PVT usali solo per questioni urgenti / personali. :)
~FullSyst3m~
10-11-2008, 13:58
Ho capito la fonte di tutti i problemi: la virgola. :D
Ecco qui:
>>> import string
>>> string.split('Qui+Quo+Qua', '+')
['Qui', 'Quo', 'Qua']
>>> string.split('Qui+Quo+Qua')
['Qui+Quo+Qua']
Con quest'esempio è più chiaro.
Io pensavo un'altra cosa.. quindi il separatore deve "fare parte" della stringa, altrimenti non ha effetto?
[QUOTE]
Perfetto. :)
Riguardo sta cosa, come mai return 1 viene appioppato a FattorialeMenoUno?
Va bene lo stesso: se ti vengono in mente delle idee, esponile pure.
Mi vengono troppe idee.. troppe domande mi faccio:D
Certamente, ma nel caso in questione la chiave potrebbe, appunto, non essere presente nel dizionario. In questo caso si usa la get.
Bè certo, in questo caso si
No, in questo caso c'è un errore perché manca la virgola alla fine della riga. Dovresti scrivere così:
Funzione(xxx, x,
x)
Sì, funziona pure perché stai elencando gli elementi di un dizionario.
Ok
In Python il tipo è definito dal valore stesso. Se scrivo 'Ciao' so che questo è un oggetto di tipo stringa. Se scrivo 123 so che questo è un intero. Se scrivo 123L so che questo è un intero lungo.
Quindi per forza di cose la L andava messa nei valori presenti nel dizionario.
Basta appendere L alla fine di ogni intero che è presente in quella funzione.
Ad esempio in Fattoriale dove si dovrebbe appendere la L?
Per favore, riportale qui. I PVT usali solo per questioni urgenti / personali. :)
Ok, scusami. Allora: riguardo Fibonacci l'unica conferma che voglio è questa: essendo che devono essere seguite due chiamate uno alla volta, si arriva alla fine, come si vede anche nel diagramma nel libro, ci sono due n = 2 (1, 0). Questa n = 2 viene calcolata una sola volta? Perchè se viene calcolata due volte allora i conti non mi tornano... non so se mi sono spiegato
~FullSyst3m~
10-11-2008, 14:01
Mentre aggiungo pure questo:
sono arrivato alla funzione CopiaFile del capitolo 11, però, come al solito del resto, alcune cose non mi tornano, e cioè:
per prima cosa ho provato a chiamare la funzione in tutti i modi, ma mi dà sempre qualche errore;
poi non capisco il perché l’f1 viene aperto subito in lettura... quando viene scritto?
cdimauro
10-11-2008, 20:13
Io pensavo un'altra cosa.. quindi il separatore deve "fare parte" della stringa, altrimenti non ha effetto?
Certo. Python "divide" la stringa non appena incontra il separatore che hai specificato.
Riguardo sta cosa, come mai return 1 viene appioppato a FattorialeMenoUno?
Perché Fattoriale(0) ritorna 1, che viene assegnato appunto a FattorialeMenoUno. E così via poi procedendo all'indietro.
Ad esempio in Fattoriale dove si dovrebbe appendere la L?
In tutti i numeri interi.
Ok, scusami. Allora: riguardo Fibonacci l'unica conferma che voglio è questa: essendo che devono essere seguite due chiamate uno alla volta, si arriva alla fine, come si vede anche nel diagramma nel libro, ci sono due n = 2 (1, 0). Questa n = 2 viene calcolata una sola volta? Perchè se viene calcolata due volte allora i conti non mi tornano... non so se mi sono spiegato
Visto che viene usato un dizionario per memorizzare tutti i valori man mano calcolati, il calcolo verrà effettuato una sola volta. Tutte le altre volte che verrà richiesto Fibonacci(2), la funzione, controllando la presenza nel dizionario, ne restituirà immediatamente il valore.
Mentre aggiungo pure questo:
sono arrivato alla funzione CopiaFile del capitolo 11, però, come al solito del resto, alcune cose non mi tornano, e cioè:
per prima cosa ho provato a chiamare la funzione in tutti i modi, ma mi dà sempre qualche errore;
Riporta l'errore.
poi non capisco il perché l’f1 viene aperto subito in lettura... quando viene scritto?
f1 è il file originale, per cui dev'essere già presente.
~FullSyst3m~
11-11-2008, 07:03
Certo. Python "divide" la stringa non appena incontra il separatore che hai specificato.
Bene
Perché Fattoriale(0) ritorna 1, che viene assegnato appunto a FattorialeMenoUno. E così via poi procedendo all'indietro.
Il procedimento ormai mi è chiaro, avevo solo la curiosità di sapere perchè l'1 viene assegnato a FattorialeMenoUno. Forse perchè FattorialeMenoUno di n = 1 è 0 che a sua volta è uguale a 1?
In tutti i numeri interi.
Si, ma in quale punto del codice?
Visto che viene usato un dizionario per memorizzare tutti i valori man mano calcolati, il calcolo verrà effettuato una sola volta. Tutte le altre volte che verrà richiesto Fibonacci(2), la funzione, controllando la presenza nel dizionario, ne restituirà immediatamente il valore.
Si, ma essendo che viene chiamata due volte, abbiamo due n = 2. Ora, viene calcolato una sola volta, nel senso che si fa una sola volta 1 + 1? Perchè altrimenti i conti non mi tornano
Riporta l'errore.
Domani lo posto
f1 è il file originale, per cui dev'essere già presente
Quindi il file si scrive prima e poi si apre in lettura per copiare il contenuto nella copia?
cdimauro
11-11-2008, 07:33
Il procedimento ormai mi è chiaro, avevo solo la curiosità di sapere perchè l'1 viene assegnato a FattorialeMenoUno. Forse perchè FattorialeMenoUno di n = 1 è 0 che a sua volta è uguale a 1?
Basta che ripercorri l'esecuzione quando entri in Fattoriale con n = 1. In questo caso hai da calcolare FattorialeMenoUno = Fattoriale(n - 1) cioé Fattoriale(0) che ritorna 1. Ecco che l'1 viene memorizzato poi in questa variabile.
Si, ma in quale punto del codice?
Dove trovi un numero.
Si, ma essendo che viene chiamata due volte, abbiamo due n = 2. Ora, viene calcolato una sola volta, nel senso che si fa una sola volta 1 + 1? Perchè altrimenti i conti non mi tornano
Si fa soltanto una volta 1 + 1 per n = 2, perché poi il risultato della somma viene messo nel dizionario, e tutte le altre volte in cui si richiede il calcolo per n = 2, si va a pescare subito il valore dal dizionario. Quindi non si fa più il calcolo.
Quindi il file si scrive prima e poi si apre in lettura per copiare il contenuto nella copia?
Certo. L'intento di quel codice è fare una copia di un file. Ma il file dev'essere già presente, altrimenti cosa si copia? ;)
~FullSyst3m~
11-11-2008, 07:44
Basta che ripercorri l'esecuzione quando entri in Fattoriale con n = 1. In questo caso hai da calcolare FattorialeMenoUno = Fattoriale(n - 1) cioé Fattoriale(0) che ritorna 1. Ecco che l'1 viene memorizzato poi in questa variabile.
Perfetto, come pensavo io :D
Dove trovi un numero.
Cosi a caso?
Si fa soltanto una volta 1 + 1 per n = 2, perché poi il risultato della somma viene messo nel dizionario, e tutte le altre volte in cui si richiede il calcolo per n = 2, si va a pescare subito il valore dal dizionario. Quindi non si fa più il calcolo.
Bene. Però quando lo aggiunge nel dizionario il valore se chiama se stessa per ben due volte fin quando n = 1? Cioè, quando c'è n = 2 poi richiama se stessa con n = 1. Siccome n = 1 c'è già va avanti con l'altra istruzione e aggiunge n = 2 al dizionario?
Certo. L'intento di quel codice è fare una copia di un file. Ma il file dev'essere già presente, altrimenti cosa si copia? ;)
Mi sembra anche giusto. Il punto è che non capisco come fare funzionare la funzione. Cioè, creo il file con:
file = open('file.txt', 'w')
file.close()
Poi nel parametro della funzione metto CopiaFile (file, ...), per la copia però cosa devo mettere? Io ho provato a mettere un nome, ad esmpio 'copy.txt', però mi dà errore
cdimauro
11-11-2008, 07:51
Cosi a caso?
Ovunque ci sia un numero.
Bene. Però quando lo aggiunge nel dizionario il valore se chiama se stessa per ben due volte fin quando n = 1? Cioè, quando c'è n = 2 poi richiama se stessa con n = 1. Siccome n = 1 c'è già va avanti con l'altra istruzione e aggiunge n = 2 al dizionario?
Ricorda che per n = 1 e n = 0 il dizionario contiene già i valori calcolati. Quando n = 2 gli servono i valori per n = 1 e 0, ma li recupera subito dal dizionario appunto.
Mi sembra anche giusto. Il punto è che non capisco come fare funzionare la funzione. Cioè, creo il file con:
file = open('file.txt', 'w')
file.close()
Poi nel parametro della funzione metto CopiaFile (file, ...), per la copia però cosa devo mettere? Io ho provato a mettere un nome, ad esmpio 'copy.txt', però mi dà errore
Creati un file col blocco note, Word, Paint, ecc. Uno qualsiasi. Mettiamo che si chiama Pippo.txt e si trovi nella stessa cartella in cui si trova il programmino Python per fare la copia. A questo punto chiama
CopiaFile('Prova.txt', 'Copia di Prova.txt')
e hai risolto. ;)
~FullSyst3m~
11-11-2008, 08:00
Ovunque ci sia un numero.
Quindi basta sfruttare la capacità d Python di convertire automaticamente gli interi, come ad esempio nel caso dei decimali che se un numero è decimale allora anche l'altro viene convertito in decimale
Ricorda che per n = 1 e n = 0 il dizionario contiene già i valori calcolati. Quando n = 2 gli servono i valori per n = 1 e 0, ma li recupera subito dal dizionario appunto.
Ma viene fatto due volte il calcolo 1 + 1? Perchè di n = 2 ce ne sono due, una nel primo Fibonacci (quello con n - 1) e l'altro nel secondo Fibonacci (quello con n - 2)
Creati un file col blocco note, Word, Paint, ecc. Uno qualsiasi. Mettiamo che si chiama Pippo.txt e si trovi nella stessa cartella in cui si trova il programmino Python per fare la copia. A questo punto chiama
CopiaFile('Prova.txt', 'Copia di Prova.txt')
e hai risolto. ;)
Questo che dici tu è nel paragrafo poco dopo, nel capitolo dove è il codice però non si parla di prendere un file già scritto. E' sottointeso che deve essere creato sempre tramite variabile = oggetto
cdimauro
11-11-2008, 08:07
Quindi basta sfruttare la capacità d Python di convertire automaticamente gli interi, come ad esempio nel caso dei decimali che se un numero è decimale allora anche l'altro viene convertito in decimale
In Python la conversione dei tipi numerici in quello che offre una maggior precisione avviene automaticamente.
Ma viene fatto due volte il calcolo 1 + 1? Perchè di n = 2 ce ne sono due, una nel primo Fibonacci (quello con n - 1) e l'altro nel secondo Fibonacci (quello con n - 2)
No, il calcolo 1 + 1 (per n = 2) viene fatto una sola volta, e poi memorizzato nel dizionario. Alla prossima richiesta per n = 2 viene tornato immediatamente perché si trova nel dizionario.
Questo che dici tu è nel paragrafo poco dopo, nel capitolo dove è il codice però non si parla di prendere un file già scritto. E' sottointeso che deve essere creato sempre tramite variabile = oggetto
No, quando parla della funzione CopiaFile si riferisce chiaramente al file "originale". Quindi preesistente.
~FullSyst3m~
11-11-2008, 08:32
In Python la conversione dei tipi numerici in quello che offre una maggior precisione avviene automaticamente.
E che ho detto io??
No, il calcolo 1 + 1 (per n = 2) viene fatto una sola volta, e poi memorizzato nel dizionario. Alla prossima richiesta per n = 2 viene tornato immediatamente perché si trova nel dizionario.
Non mi sono spiegato. Io non intendo il calcolo di per sè, ma il risultato. Facendo il procedimento su carta e penna, se 1 + 1 lo scrivo una sola volta allora i conti tornano, altrimenti no. Non so se capisci che voglio dire
No, quando parla della funzione CopiaFile si riferisce chiaramente al file "originale". Quindi preesistente.
Si, siamo d'accordo, però da creare tramite quello che ha spiegato, non da prendere dalla cartella (quello è il paragrafo immediatamente successivo)
~FullSyst3m~
11-11-2008, 09:46
Io avevo intenzione di fare una cosa del genere:
def CopiaFile (Originale, Copia):
f1 = open(Originale, 'r')
f2 = open(Copia, 'w')
while 1:
Testo = f1.read(50)
if Testo == "":
break
f2.write(Testo)
f1.close()
f2.close()
return
f = open('prova.txt', 'w')
f.write('Ciao questa è una prova')
f.close()
CopiaFile (f, 'copia.txt')
però pyscripter mi dice:
“exceptions.TypeError: coercing to Unicode: need string or buffer, file found”
CopiaFile (f, 'copia.txt')
L'errore è qui. La variabile f è una stringa? Che cosa contiene quando viene chiamata la funzione?
cdimauro
11-11-2008, 12:52
E che ho detto io??
Volevo solo esplicitare. :)
Non mi sono spiegato. Io non intendo il calcolo di per sè, ma il risultato. Facendo il procedimento su carta e penna, se 1 + 1 lo scrivo una sola volta allora i conti tornano, altrimenti no. Non so se capisci che voglio dire
Spero di sì. Il calcolo lo fai una sola volta, appunto. Il risultato dipende esclusivamente dal dizionario.
Si, siamo d'accordo, però da creare tramite quello che ha spiegato, non da prendere dalla cartella (quello è il paragrafo immediatamente successivo)
Ti ha risposto Vicius: non puoi passare un oggetto file a una funzione che si aspetta soltanto il nome del file (perché poi ci pensa lei ad aprirlo). ;)
~FullSyst3m~
11-11-2008, 13:09
L'errore è qui. La variabile f è una stringa? Che cosa contiene quando viene chiamata la funzione?
La variabile f è un file che ho creato e scritto, infatti è presente nella cartella. Inserendo la variabile automaticamente dovrebbe riferirsi al file
Volevo solo esplicitare.
:ave:
Spero di sì. Il calcolo lo fai una sola volta, appunto. Il risultato dipende esclusivamente dal dizionario.
Mi sa che non hai capito. Adesso non ho tempo di spiegare meglio, prova a rileggere i messaggi passati se non capisci quando posso cerco di spiegare meglio
Ti ha risposto Vicius: non puoi passare un oggetto file a una funzione che si aspetta soltanto il nome del file (perché poi ci pensa lei ad aprirlo).
Si aspetta il nome del file, però il file è "collegato" ad f. Quel preciso paragrafo non spiega di creare un file e poi aprirlo, ma spiega come crearlo tramite open(file, modo) e come scriverlo con f.write(). Capito che voglio dire?
La variabile f è un file che ho creato e scritto, infatti è presente nella cartella. Inserendo la variabile automaticamente dovrebbe riferirsi al file
È qui che sbagli. La open accetta in ingresso solo stringhe con il nome del file da aprire e non oggetti file già aperti.
~FullSyst3m~
11-11-2008, 13:54
È qui che sbagli. La open accetta in ingresso solo stringhe con il nome del file da aprire e non oggetti file già aperti.
Ah ora ho capito. Quindi se io apro un file e lo affibio a f non posso passare f come parametro...
DanieleC88
11-11-2008, 18:13
Ah ora ho capito. Quindi se io apro un file e lo affibio a f non posso passare f come parametro...
Teoricamente non c'è niente che impedisca ad f di essere passata come parametro, anzi, in alcuni casi ti può essere anche utilissimo. Più semplicemente, siccome CopiaFile() si aspetta di ricevere due stringhe in input, i parametri non possono essere oggetti di diverso tipo, altrimenti otterrai un errore (o, nel peggiore dei casi, un'esecuzione che si comporta silenziosamente in modo diverso dal previsto). ;)
~FullSyst3m~
11-11-2008, 18:53
Teoricamente non c'è niente che impedisca ad f di essere passata come parametro, anzi, in alcuni casi ti può essere anche utilissimo. Più semplicemente, siccome CopiaFile() si aspetta di ricevere due stringhe in input, i parametri non possono essere oggetti di diverso tipo, altrimenti otterrai un errore (o, nel peggiore dei casi, un'esecuzione che si comporta silenziosamente in modo diverso dal previsto). ;)
E' inquietante la frase "un'esecuzione che si comporta silenziosamente in modo diverso dal previsto" :D
cdimauro
11-11-2008, 19:40
Mi sa che non hai capito. Adesso non ho tempo di spiegare meglio, prova a rileggere i messaggi passati se non capisci quando posso cerco di spiegare meglio
Ah. Allora mi spiace, ma non ho afferrato. :boh:
Si aspetta il nome del file, però il file è "collegato" ad f. Quel preciso paragrafo non spiega di creare un file e poi aprirlo, ma spiega come crearlo tramite open(file, modo) e come scriverlo con f.write(). Capito che voglio dire?
Sì, ma devi anche vedere come funziona la open. La open si aspetta un parametro obbligatorio che è il nome del file, per cui se gli passi un file già aperto chiaramente non può funzionare.
DanieleC88
11-11-2008, 20:44
E' inquietante la frase "un'esecuzione che si comporta silenziosamente in modo diverso dal previsto" :D
Lo è lo è, gli errori più "simpatici" sono quelli che si fanno vedere: quelli che non si fanno vedere sono la peggior specie. :asd:
~FullSyst3m~
11-11-2008, 21:58
Lo è lo è, gli errori più "simpatici" sono quelli che si fanno vedere: quelli che non si fanno vedere sono la peggior specie. :asd:
Eh lo so, sono subdoli quegli errori. Se però un linguaggio ha un buon controllo sui tipi dovrebbero diminuire (adesso sto parlando solo riguardo quello che avevi detto tu non in generale)
Ah. Allora mi spiace, ma non ho afferrato.
Vedo di spiegarla cosi: Fibonacci (4):
n = 4
n = 3 + n = 2 (che per il momento resta congelata) --> 3 + 2
n = 3 è uguale a n = 2 + n = 1 (valore preso dal dizionario) --> 2 + 1
n = 2 è uguale a n = 1 (preso dal dizionario) + n = 0 (preso dal dizionario) --> 1 + 1
Ora si torna alla n = 2 congelata di prima che sarebbe n = 1 (preso dal dizionario) + n = 0 (preso dal dizionario) --> 1 + 1
In definitiva abbiamo:
3 + 2
2 + 1
1 + 1
1 + 1
Ora, quell'n = 2 ( 1 + 1 ) viene calcolato una vola? Perchè se viene calcolato una volta i conti tornano, altrimenti non mi tornano. Se viene calcolato una volta abbiamo:
3 + 2
2 + 1
1 + 1
Capito ora?
Sì, ma devi anche vedere come funziona la open. La open si aspetta un parametro obbligatorio che è il nome del file, per cui se gli passi un file già aperto chiaramente non può funzionare.
Io il file lo avevo chiuso, le ho passato il nome della variabile del file chiuso che poi la funzione doveva aprire in lettura. Comunque il tuo ragionamento non è sbagliato, anzi. Però voglio farti cercare di capire le mie ipotesi
cdimauro
12-11-2008, 08:22
Vedo di spiegarla cosi: Fibonacci (4):
n = 4
n = 3 + n = 2 (che per il momento resta congelata) --> 3 + 2
n = 3 è uguale a n = 2 + n = 1 (valore preso dal dizionario) --> 2 + 1
n = 2 è uguale a n = 1 (preso dal dizionario) + n = 0 (preso dal dizionario) --> 1 + 1
Ora si torna alla n = 2 congelata di prima che sarebbe n = 1 (preso dal dizionario) + n = 0 (preso dal dizionario) --> 1 + 1
In definitiva abbiamo:
3 + 2
2 + 1
1 + 1
1 + 1
Ora, quell'n = 2 ( 1 + 1 ) viene calcolato una vola? Perchè se viene calcolato una volta i conti tornano, altrimenti non mi tornano. Se viene calcolato una volta abbiamo:
3 + 2
2 + 1
1 + 1
Capito ora?
Chiarissimo e... hai centrato perfettamente il problema (n = 2 viene effettivamente calcolato una sola volta). Complimenti! :)
Io il file lo avevo chiuso, le ho passato il nome della variabile del file chiuso che poi la funzione doveva aprire in lettura. Comunque il tuo ragionamento non è sbagliato, anzi. Però voglio farti cercare di capire le mie ipotesi
Sì, ho capito. Devi comunque tenere a mente che si tratta di oggetti diversi: un conto è l'oggetto file e tutt'altra cosa è il nome del file (che è una stringa).
Le funzioni (e i metodi) si aspettano (quasi) sempre degli oggetti precisi come parametri. Nel caso della open, come primo parametro accetta soltanto stringhe, appunto.
Il mio consiglio, quando usi una funzione a te estranea, è di controllare sempre che tipo è richiesto per i parametri. In questo modo eviterai problemi come questo, appunto. ;)
~FullSyst3m~
12-11-2008, 10:17
Chiarissimo e... hai centrato perfettamente il problema (n = 2 viene effettivamente calcolato una sola volta). Complimenti! :)
:D Thanks!
Sì, ho capito. Devi comunque tenere a mente che si tratta di oggetti diversi: un conto è l'oggetto file e tutt'altra cosa è il nome del file (che è una stringa).
Le funzioni (e i metodi) si aspettano (quasi) sempre degli oggetti precisi come parametri. Nel caso della open, come primo parametro accetta soltanto stringhe, appunto.
Il mio consiglio, quando usi una funzione a te estranea, è di controllare sempre che tipo è richiesto per i parametri. In questo modo eviterai problemi come questo, appunto. ;)
Si infatti. Siccome nel libro c'è messo che come parametri si aspetta il nome del file e il metodo allora ho provato passando l'oggetto del file per vedere che succedeva. Anche perchè, non essendo specificato che voleva solo stringhe, e dato che non si accennava al fatto di creare un file prima e metterlo nella cartella del programma, allora ho pensato che il file si doveva creare con write e poi usare quello come parametro ;)
Piccola curoisità: nel capitolo 11.2 c'è scritto: "Il primo operando in questo caso è la stringa di formato ed il secondo una tupla di espressioni. Il risultato è una stringa formattata secondo la stringa di formato."
Nell'esempio prima di queste righe non c'è nessuna tupla, quindi non deve essere una tupla per forza quello che c'è dopo la sequenza di formato, o no?. Poi, la stringa di formato sarebbe la stringa da stampare? Perchè quella frase di sopra non si capisce a cosa si riferisce...
Comunque nella funzione Report c'è il print che ha %-20s e %12.02f. Gli spazi poi si "uniscono" oppure in totale abbiamo 32 spazi? Perchè il meno mette gli spazi alla destra, l'altro invece alla sinistra. Ah, un'altra cosa: perchè hanno scritto 12.02? Se si metteva 12.2 era la stessa identica cosa
P.S: ho fatto stampare il libro in una copisteria... è venuto proprio carino :)
grigor91
12-11-2008, 16:46
Nell'esempio prima di queste righe non c'è nessuna tupla, quindi non deve essere una tupla per forza quello che c'è dopo la sequenza di formato, o no?.
Esatto
Poi, la stringa di formato sarebbe la stringa da stampare? Perchè quella frase di sopra non si capisce a cosa si riferisce...
Sarebbe "%d" e simili...
Comunque nella funzione Report c'è il print che ha %-20s e %12.02f. Gli spazi poi si "uniscono" oppure in totale abbiamo 32 spazi? Perchè il meno mette gli spazi alla destra, l'altro invece alla sinistra.
Abbiamo 20 spazi, in parte occupati a partire da sinistra, affiancati da 12 spazi, in parte occupati a partire da destra. Nella stampa sembrano uniti, ma in realtà sono affiancati.
Ah, un'altra cosa: perchè hanno scritto 12.02? Se si metteva 12.2 era la stessa identica cosa
Sì sono uguali.
~FullSyst3m~
12-11-2008, 17:45
Sarebbe "%d" e simili...
No, quella è una sequenza di formato
Abbiamo 20 spazi, in parte occupati a partire da sinistra, affiancati da 12 spazi, in parte occupati a partire da destra. Nella stampa sembrano uniti, ma in realtà sono affiancati.
Volevo sapere solo se erano uniti o indipendenti anche se affiancati
Sì sono uguali
Questo l'ho visto e detto pure io, la domanda era perchè scrivere 12.02 quando 12.2 è la stessa cosa
Questo l'ho visto e detto pure io, la domanda era perchè scrivere 12.02 quando 12.2 è la stessa cosa
12.02 e 12.2 NON sono la stessa cosa :)
~FullSyst3m~
12-11-2008, 18:08
12.02 e 12.2 NON sono la stessa cosa :)
Io ho fatto alcune prove con alcuni numeri decimali a scriverli prima con lo 0 davanti e poi senza e il risultato era sempre uguale. Le mie affermazioni erano basate su questo
Io ho fatto alcune prove con alcuni numeri decimali a scriverli prima con lo 0 davanti e poi senza e il risultato era sempre uguale. Le mie affermazioni erano basate su questo
Questi sono dubbi che non dovresti avere. Appena finito questo libro su python devi fiondarti sui vecchi libri di matematica delle medie e superiori e fare un ripasso generale su tutto. Queste sono cose che si facevano alle elementari e non dovresti pensarci nemmeno 1 secondo per avere la risposta giusta.
~FullSyst3m~
12-11-2008, 20:16
Questi sono dubbi che non dovresti avere. Appena finito questo libro su python devi fiondarti sui vecchi libri di matematica delle medie e superiori e fare un ripasso generale su tutto. Queste sono cose che si facevano alle elementari e non dovresti pensarci nemmeno 1 secondo per avere la risposta giusta.
Che devo fare una full immersion di matematica lo sapevo già, visto anche il fatto che devo andare all'uni il prossimo anno, ma io mi sono solo basato sull'output ricevuto dall'interprete che è uguale in tutti e due i casi. Non penso di aver detto una cosa tabù :(
~FullSyst3m~
13-11-2008, 12:04
def Function ():
try:
InputNumero()
return "Ok"
except:
return "Non ok"
print Function()
Ecco cosa ottengo mettendo un numero maggiore di 17:
DeprecationWarning: raising a string exception is deprecated
raise 'ErroreNumero', 'mi aspetto numeri minori di 17!'
Non ok
Inoltre, non capisco perchè questo codice non è possibile:
http://www.hwupgrade.it/forum/showpost.php?p=24770186&postcount=179
def Function ():
try:
InputNumero()
return "Ok"
except:
return "Non ok"
print Function()
Ecco cosa ottengo mettendo un numero maggiore di 17:
DeprecationWarning: raising a string exception is deprecated
raise 'ErroreNumero', 'mi aspetto numeri minori di 17!'
Non ok
È solo un warning non ti preoccupare. Probabilmente hanno intenzione di rimuovere la possibilità di lanciare eccezioni stringa in qualche versione futura ma a te questo non deve interessare.
Inoltre, non capisco perchè questo codice non è possibile:
http://www.hwupgrade.it/forum/showpost.php?p=24770186&postcount=179
Il codice è corretto solo che non funziona perché ovviamente if e print non lanciano mai eccezioni quindi il codice inserito dopo la except non viene mai eseguito.
~FullSyst3m~
13-11-2008, 12:20
È solo un warning non ti preoccupare. Probabilmente hanno intenzione di rimuovere la possibilità di lanciare eccezioni stringa in qualche versione futura ma a te questo non deve interessare.
E ti avvisano? Bella questa.. comunque questa è un'eccezione stringa? Perchè nel libro non viene detto
Il codice è corretto solo che non funziona perché ovviamente if e print non lanciano mai eccezioni quindi il codice inserito dopo la except non viene mai eseguito.
Ah è vero, allora l'altro codice del libro, cioè quello della funzione FileEsiste, funziona perchè se il file non c'è l'eccezione viene sollevata in automatico da Python, giusto?
cdimauro
13-11-2008, 13:05
È solo un warning non ti preoccupare. Probabilmente hanno intenzione di rimuovere la possibilità di lanciare eccezioni stringa in qualche versione futura ma a te questo non deve interessare.
Togli il probabilmente: da Python 3.0 in poi non sarà possibile usare le stringhe per sollevare eccezioni, ma si dovrà necessariamente instanziare un'opportuna classe. :)
~FullSyst3m~
13-11-2008, 14:02
Togli il probabilmente: da Python 3.0 in poi non sarà possibile usare le stringhe per sollevare eccezioni, ma si dovrà necessariamente instanziare un'opportuna classe. :)
Cioè? Ma in questo esempio dove vengono usate le stringhe? Quando si descrive l'errore dopo il raise?
~FullSyst3m~
13-11-2008, 14:25
Comunque alla fine usando try / except il programma si blocca comunque anche se viene gestita l'eccezione, la stessa cosa vale se si solleva. Il programma non continua a funzionare in questi due casi
grigor91
13-11-2008, 15:40
No, quella è una sequenza di formato
Sì scusami :D
In questo esempio:
"In luglio abbiamo venduto %d automobili." % NumAuto
la stringa di formato è questa:
"In luglio abbiamo venduto %d automobili."
cioè quello che sta alla sinistra dell'operatore %
~FullSyst3m~
13-11-2008, 17:50
Sì scusami :D
In questo esempio:
"In luglio abbiamo venduto %d automobili." % NumAuto
la stringa di formato è questa:
"In luglio abbiamo venduto %d automobili."
cioè quello che sta alla sinistra dell'operatore %
Quello che ho detto io :D
cdimauro
13-11-2008, 19:53
Cioè? Ma in questo esempio dove vengono usate le stringhe? Quando si descrive l'errore dopo il raise?
Esattamente:
raise 'ErroreNumero', 'mi aspetto numeri minori di 17!'
Il primo parametro di raise sarà obbligatoriamente una classe o una sua istanza a partire da Python 3.0.
~FullSyst3m~
13-11-2008, 20:52
Esattamente:
raise 'ErroreNumero', 'mi aspetto numeri minori di 17!'
Il primo parametro di raise sarà obbligatoriamente una classe o una sua istanza a partire da Python 3.0.
Quindi al posto di 'ErroreNumero' (esempio) ci sarà o una classe o un oggetto?
Come mai sta scelta? Cosi mi sembra più comodo. Cioè, se si deve sollevare un'eccezione si deve mettere come parametro una classe o un oggetto?
cdimauro
13-11-2008, 21:13
Qualche ora fa a lavoro ho creato una nuova classe per sollevare eccezioni in presenza di timeout:
class TimeoutError(IOError): pass
raise TimeoutError
Non è comodo come specificare una stringa direttamente, com'è possibile adesso, ma lo trovo di gran lunga più leggibile. ;)
~FullSyst3m~
13-11-2008, 21:44
Qualche ora fa a lavoro ho creato una nuova classe per sollevare eccezioni in presenza di timeout:
class TimeoutError(IOError): pass
raise TimeoutError
Non è comodo come specificare una stringa direttamente, com'è possibile adesso, ma lo trovo di gran lunga più leggibile. ;)
Com'è possibile adesso non è che sia poco leggibile però.
Riguardo la classe, io ho iniziato proprio oggi a studiarle, ma dopo i due punti so che si dovrebbe andare a capo e indentare il blocco di istruzioni, proprio come le funzioni. Inoltre, il raise non dovrebbe prendere due parametri?
P.S: non è finita la classe che hai scritto immagino visto il pass...
cdimauro
14-11-2008, 07:25
Com'è possibile adesso non è che sia poco leggibile però.
Perché c'è una differenza abissale fra una stringa e una classe. Quando vedo una raise io la associo immediatamente a un oggetto che si porta dietro informazioni su ciò che è avvenuto, e una stringa mi suona come qualcosa di profondamento diverso.
Sarà anche questione di abitudine, eh!
Riguardo la classe, io ho iniziato proprio oggi a studiarle, ma dopo i due punti so che si dovrebbe andare a capo e indentare il blocco di istruzioni, proprio come le funzioni.
Non necessariamente. Se la tua classe presenta soltanto istruzioni da eseguire, puoi mettere tutto dopo i due punti e non andare necessariamente a capo:
>>> class punto: x = 0; y = 0
...
>>> punto
<class __main__.punto at 0x0261AE40>
>>> dir(punto)
['__doc__', '__module__', 'x', 'y']
ma te lo sconsiglio fortemente perché è poco leggibile.
Moooolto meglio così:
>>> class punto:
x = 0
y = 0
O così:
>>> class punto:
x = y = 0
Inoltre, il raise non dovrebbe prendere due parametri?
Soltanto il primo è obbligatorio.
P.S: non è finita la classe che hai scritto immagino visto il pass...
No, il pass significa semplicemente: "non ci sono istruzioni da eseguire". La classe si chiude quando viene chiusa l'indentazione.
Quindi una classe può anche essere completa (come definizione) ma del tutto vuota e non avere né variabili di classe né metodi dichiarati. ;)
~FullSyst3m~
14-11-2008, 07:54
Perché c'è una differenza abissale fra una stringa e una classe. Quando vedo una raise io la associo immediatamente a un oggetto che si porta dietro informazioni su ciò che è avvenuto, e una stringa mi suona come qualcosa di profondamento diverso.
Sarà anche questione di abitudine, eh!
Un esempio di un raise con un oggetto si può avere?
Non necessariamente. Se la tua classe presenta soltanto istruzioni da eseguire, puoi mettere tutto dopo i due punti e non andare necessariamente a capo:
>>> class punto: x = 0; y = 0
...
>>> punto
<class __main__.punto at 0x0261AE40>
>>> dir(punto)
['__doc__', '__module__', 'x', 'y']
ma te lo sconsiglio fortemente perché è poco leggibile.
Moooolto meglio così:
>>> class punto:
x = 0
y = 0
O così:
>>> class punto:
x = y = 0
Io la sto studiando in modo diverso. Inoltre hai detto che se presenta solo istruzioni da eseguire si può inserire tutto dopo i due punti, ma una classe non dovrebbe avere sempre istruzioni da seguire? Ancora non mi sono molto chiare ste cose, ho iniziato ieri a farle
dir(Punto) cosa è? E' il parametro IOError a cosa serve?
Soltanto il primo è obbligatorio.
Ok
No, il pass significa semplicemente: "non ci sono istruzioni da eseguire". La classe si chiude quando viene chiusa l'indentazione.
Ma si potrebbe pure mettere per indicare che il codice di quella classe (o funzione) deve ancora essere scritto
Quindi una classe può anche essere completa (come definizione) ma del tutto vuota e non avere né variabili di classe né metodi dichiarati. ;)
E che senso ha creare una classe cosi?
cdimauro
14-11-2008, 08:31
Un esempio di un raise con un oggetto si può avere?
Te l'ho dato sopra: raise IOError :)
Io la sto studiando in modo diverso. Inoltre hai detto che se presenta solo istruzioni da eseguire si può inserire tutto dopo i due punti, ma una classe non dovrebbe avere sempre istruzioni da seguire? Ancora non mi sono molto chiare ste cose, ho iniziato ieri a farle
E quindi hai tempo per approfondirle, per cui non te ne preoccupare adesso. ;)
dir(Punto) cosa è?
Una funzione standard che riporta l'elenco di tutti gli attribuiti di un oggetto.
E' il parametro IOError a cosa serve?
E' una particolare eccezione.
Ma si potrebbe pure mettere per indicare che il codice di quella classe (o funzione) deve ancora essere scritto
No. La classe, come ho già detto, si chiude con l'indentazione. Se successivamente definisci nuovamente la classe punto, questa sarà un'altra nonché nuova definizione, anche se dovessi riscriverla esattamente come prima (in pratica verrebbe creato un nuovo oggetto che si chiama con lo stesso nome).
E che senso ha creare una classe cosi?
E' comodissima per conservare delle informazioni che hanno un'etichetta:
class bag: pass
a = bag()
a.X = 0
a.Y = 1
a.Nome = 'Pippo'
print a.X, a.Y, a.Nome
;)
~FullSyst3m~
14-11-2008, 09:17
Te l'ho dato sopra: raise IOError :)
Scusa, non lo sapevo che era un oggetto
E quindi hai tempo per approfondirle, per cui non te ne preoccupare adesso. ;)
Mi preoccupo invece..:D
Una funzione standard che riporta l'elenco di tutti gli attribuiti di un oggetto.
Ok
E' una particolare eccezione.
Quindi cosa significa quella classe?
No. La classe, come ho già detto, si chiude con l'indentazione. Se successivamente definisci nuovamente la classe punto, questa sarà un'altra nonché nuova definizione, anche se dovessi riscriverla esattamente come prima (in pratica verrebbe creato un nuovo oggetto che si chiama con lo stesso nome).
Si riguardo le funzioni che riguardo le classi nel libro c'è messo che pass si mette quando magari si è iniziato a scrivere una funzione o una classe ma ancora si deve inserire il corpo, e sta a significare che si prevede un corpo che dovrà essere scritto. Riguardo l'indentazione è come la funzione, quando finisce si chiude, mi sembra logico;)
E' comodissima per conservare delle informazioni che hanno un'etichetta:
class bag: pass
a = bag()
a.X = 0
a.Y = 1
a.Nome = 'Pippo'
print a.X, a.Y, a.Nome
;)
E' proprio come quella che sto studiando nel libro:
class Punto:
pass
Per etichetta cosa intendi?
Comunque quando all'inizio del capitolo 12 dice che abbiamo usato dei tipi composti predefiniti, si riferisce alle stringhe, alle tuple ecc?
P.S: ma i pm ti sono arrivati ieri sera? Perchè la connessione faceva le bizze
~FullSyst3m~
14-11-2008, 09:36
Doppio post (maledetta 56k)
~FullSyst3m~
14-11-2008, 10:41
L'identificatore di P1 è diverso da quello di Punto. Come mai? P1 si riferisce all'oggetto Punto quindi dovrebbero avere lo stesso id oppure
~FullSyst3m~
14-11-2008, 17:19
Paragrafo 12.7:
1) Parla di metodo, a cosa si riferisce di preciso? Perchè io vedo funzioni e oggetti
2) R1.AltoSinistra.x = 0.0; Perchè la il punto e virgola finale?
3) class Punto:
pass
class Rettangolo:
pass
def AumentaRettangolo(Rettangolo, AumentoLargh, AumentoAlt):
Rett.Larghezza = Rett.Larghezza + AumentoLargh
Rett.Altezza = Rett.Altezza + AumentoAlt
return Rett.Altezza
return Rett.Larghezza
R1 = Rettangolo()
R1.Larghezza = 100.0
R1.Altezza = 200.0
R1.AltoSinistra = Punto()
R1.AltoSinistra.x = 0.0
R1.AltoSinistra.y = 0.0
print AumentaRettangolo(R1, 50, 100)
mi stampa solo il primo return, il secondo no. A meno che non le metto come tuple
return Rett.Altezza, Rett.Larghezza
P.S: come al solito se metto il print davanti, ad esempio, a Rett.Larghezza = Rett.Larghezza + AumentoLargh mi dà errore, però nei primi capitoli il print per le operazioni veniva usato sempre in pratica. Mha...
DanieleC88
14-11-2008, 17:46
1) Parla di metodo, a cosa si riferisce di preciso? Perchè io vedo funzioni e oggetti
A loro. :D
mi stampa solo il primo return, il secondo no. A meno che non le metto come tuple
Le devi mettere come tuple, il return spezza il flusso di esecuzione della funzione, interrompendola dove ti trovi. Quindi il secondo return non verrà mai raggiunto. ;)
DanieleC88
14-11-2008, 17:49
P.S: come al solito se metto il print davanti, ad esempio, a Rett.Larghezza = Rett.Larghezza + AumentoLargh mi dà errore, però nei primi capitoli il print per le operazioni veniva usato sempre in pratica. Mha...
Perché è un'operazione di assegnazione, non puoi "stamparla", è una cosa che probabilmente spesso vedresti in un codice C, ma non mi risulta che in Python esista.
Prova a fare:
print a = 3 + 2
E vedrai che l'interprete si lamenterà subito. Prova invece così:
a = 3 + 2
print a
ciao ;)
~FullSyst3m~
14-11-2008, 20:47
A loro. :D
Vengono chiamate metodi? Non lo sapevo, il libro non dice nulla a riguardo
Le devi mettere come tuple, il return spezza il flusso di esecuzione della funzione, interrompendola dove ti trovi. Quindi il secondo return non verrà mai raggiunto. ;)
Hai ragione, oggi proprio sono esausto e non ragiono :(
~FullSyst3m~
14-11-2008, 20:48
Perché è un'operazione di assegnazione, non puoi "stamparla", è una cosa che probabilmente spesso vedresti in un codice C, ma non mi risulta che in Python esista.
Prova a fare:
print a = 3 + 2
E vedrai che l'interprete si lamenterà subito. Prova invece così:
a = 3 + 2
print a
ciao ;)
Queste sono cose che ho fatto nel primo capitolo, però non veniva spiegato che non si possono stampare le assegnazioni. Curiosità personale, tutto qua
DanieleC88
14-11-2008, 23:13
Vengono chiamate metodi? Non lo sapevo, il libro non dice nulla a riguardo
Funzioni, metodi, procedure, routine... le troverai chiamate in parecchi modi, ma sono sinonimi. :)
AnonimoVeneziano
15-11-2008, 01:03
Beh, vengono chiamati metodi le funzioni collegate all'istanza di una classe. Insomma le funzioni definite all'interno di una definizione di classe sono detti metodi
~FullSyst3m~
15-11-2008, 07:39
Beh, vengono chiamati metodi le funzioni collegate all'istanza di una classe. Insomma le funzioni definite all'interno di una definizione di classe sono detti metodi
Nel caso di prima non abbiamo funzioni definite dentro una classe, abbiamo solo delle funzioni che sono collegate all'oggetto di una classe. Nel caso di prima il metodo sarebbe AumentaRettangolo considerata quest'ultima cosa. Comunque il libro è molto generico su questo eh..
DanieleC88
15-11-2008, 12:37
Nel caso di prima non abbiamo funzioni definite dentro una classe, abbiamo solo delle funzioni che sono collegate all'oggetto di una classe. Nel caso di prima il metodo sarebbe AumentaRettangolo considerata quest'ultima cosa. Comunque il libro è molto generico su questo eh..
Ripeto, sono tutti sinonimi: spesso vengono utilizzati con sfumature un po' diverse (come questa di "metodo"), ma sono la stessa cosa.
~FullSyst3m~
15-11-2008, 12:43
Ripeto, sono tutti sinonimi: spesso vengono utilizzati con sfumature un po' diverse (come questa di "metodo"), ma sono la stessa cosa.
Siamo d'accordo, se però leggi cosa ha scritto AnonimoVeneziano la cosa vacilla e non è più cosi "generica" come dici tu
AnonimoVeneziano
15-11-2008, 12:53
Siamo d'accordo, se però leggi cosa ha scritto AnonimoVeneziano la cosa vacilla e non è più cosi "generica" come dici tu
Va bene essere formali , ma così è un po' troppo :D
DanieleC88
15-11-2008, 13:22
Cavoli, in effetti... :asd:
~FullSyst3m~
15-11-2008, 14:05
Va bene essere formali , ma così è un po' troppo :D
In che senso? Che ho detto di strano??:confused:
Non ti fare di questi problemi. L'unico linguaggio in cui metodi e funzioni avevano un comportamento leggermente differente e richiedevano una sintassi diversa era il vecchio visual basic. Ora grazie al cielo hanno tolto questa idiozia nelle nuove versioni .net.
In linguaggi come python in cui tutto è un oggetto questa distinzione non esiste. Non mi stupirebbe affatto se python aggiungesse silenziosamente tutti i metodi definiti al di fuori di una classe ad un oggetto base tipo Kernel come fa ruby, quindi di fatto sono tutti metodi.
~FullSyst3m~
15-11-2008, 15:10
Non ti fare di questi problemi. L'unico linguaggio in cui metodi e funzioni avevano un comportamento leggermente differente e richiedevano una sintassi diversa era il vecchio visual basic. Ora grazie al cielo hanno tolto questa idiozia nelle nuove versioni .net.
In linguaggi come python in cui tutto è un oggetto questa distinzione non esiste. Non mi stupirebbe affatto se python aggiungesse silenziosamente tutti i metodi definiti al di fuori di una classe ad un oggetto base tipo Kernel come fa ruby, quindi di fatto sono tutti metodi.
Cioè?
Comunque vengono chiamate metodi tutte le funzioni o solo quelle riferite o incluse in una classe?
AnonimoVeneziano
15-11-2008, 15:11
In che senso? Che ho detto di strano??:confused:
Nel senso che a volte anche i libri utilizzano termini sbagliando il contesto .
I metodi sono funzioni definite in classi
Le funzioni/procedure sono definite nello spazio globale.
Questa è la definizione più diffusa e conosciuta. Che poi magari un libro scriva metodo quando avrebbe dovuto scrivere funzione o viceversa ha poca importanza :)
Cioè?
In ruby, dove tutto quanto è un oggetto, una funzione deve essere per forza associata ad una classe, non può esistere da sola. Quando definisci un metodo fuori da una classe l'interprete ruby invece di picchiarti chiude un occhio. Di fatto prende il tuo codice e la aggiunge a quello nella classe Kernel. Python e ruby hanno molti punti in comune quindi suppongo che anche il pitone funzioni in maniera simile ma non prendere queste cose per oro colato finche non passa cesare a darci una conferma.
~FullSyst3m~
15-11-2008, 17:12
Nel senso che a volte anche i libri utilizzano termini sbagliando il contesto .
I metodi sono funzioni definite in classi
Le funzioni/procedure sono definite nello spazio globale.
Questa è la definizione più diffusa e conosciuta. Che poi magari un libro scriva metodo quando avrebbe dovuto scrivere funzione o viceversa ha poca importanza :)
Eh infatti! Lo so benissimo questo, per questo ho detto quelle cose! Sono stato frainteso evidentemente ;)
In ruby, dove tutto quanto è un oggetto, una funzione deve essere per forza associata ad una classe, non può esistere da sola. Quando definisci un metodo fuori da una classe l'interprete ruby invece di picchiarti chiude un occhio. Di fatto prende il tuo codice e la aggiunge a quello nella classe Kernel. Python e ruby hanno molti punti in comune quindi suppongo che anche il pitone funzioni in maniera simile ma non prendere queste cose per oro colato finche non passa cesare a darci una conferma.
Va bene, comunque è molto interessante sapere queste cose. Ma tutte le cose che sa Cesare su Python le ha studiate nella documentazione ufficiale secondo voi?
Va bene, comunque è molto interessante sapere queste cose. Ma tutte le cose che sa Cesare su Python le ha studiate nella documentazione ufficiale secondo voi?
Secondo me si fa prima con un buon libro. Poi per rimanere aggiornati basta leggersi la documentazione e le note di rilascio ad ogni nuova versione. :)
AnonimoVeneziano
15-11-2008, 23:15
Per imparare a programmare c'è un solo modo :
Programmare.
La teoria è importante per farsi le basi e poter iniziare a lavorare, ma la vera conoscenza nel programmare la si fa solo sporcandosi le mani, perchè è lì che tutti i concetti che si pensava di aver capito alla perfezione appena letti sul libro si scoprono essere stati completamente fraintesi.
Per quanto mi riguarda credo di aver iniziato veramente la mia strada di apprendimento della programmazione solo quando ho deciso di farmi il mio vero primo progettino personale discostandomi dalla riproduzione degli esempi di libri/tutorial .
Poi è ovvio che quando si è agli inizi non ci si può permettere di buttarsi nel buio e iniziare a farsi una applicazione completa, ma è sufficente porsi un obiettivo, anche una calcolatrice testuale o altre applicazioni della stessa difficoltà realizzative vanno bene, basta iniziare a stimolare il cervello a risolvere i problemi.
~FullSyst3m~
16-11-2008, 08:10
Per imparare a programmare c'è un solo modo :
Programmare.
La teoria è importante per farsi le basi e poter iniziare a lavorare, ma la vera conoscenza nel programmare la si fa solo sporcandosi le mani, perchè è lì che tutti i concetti che si pensava di aver capito alla perfezione appena letti sul libro si scoprono essere stati completamente fraintesi.
Per quanto mi riguarda credo di aver iniziato veramente la mia strada di apprendimento della programmazione solo quando ho deciso di farmi il mio vero primo progettino personale discostandomi dalla riproduzione degli esempi di libri/tutorial .
Poi è ovvio che quando si è agli inizi non ci si può permettere di buttarsi nel buio e iniziare a farsi una applicazione completa, ma è sufficente porsi un obiettivo, anche una calcolatrice testuale o altre applicazioni della stessa difficoltà realizzative vanno bene, basta iniziare a stimolare il cervello a risolvere i problemi.
Non lo metto in dubbio che per imparare a programmare si deve programmare, però per iniziare a stimolare il cervello e farsi i propri progettini discostandosi dagli esercizi del libro si deve sempre avere una base e conoscere almeno le basi di un linguaggio. Nel mio caso almeno il libro lo dovrei finire, o sbaglio?
Inoltre mi succede sempre una cosa strana: non capisco perchè se leggo un codice capisco cosa fa, però se mi chiedo se riuscissi a farlo io la risposta è sempre no.
Secondo me si fa prima con un buon libro. Poi per rimanere aggiornati basta leggersi la documentazione e le note di rilascio ad ogni nuova versione
Il libro ufficiale del linguaggio credo che sia un buon libro non credi?
~FullSyst3m~
16-11-2008, 18:09
Perché è un'operazione di assegnazione, non puoi "stamparla", è una cosa che probabilmente spesso vedresti in un codice C, ma non mi risulta che in Python esista.
Prova a fare:
print a = 3 + 2
E vedrai che l'interprete si lamenterà subito. Prova invece così:
a = 3 + 2
print a
ciao ;)
Ho fatto qualche prova e il problema non è questo che hai detto tu. Se stampo i risultati come tuple non ci sono problemi, se li metto invece uno sotto l'altro come nell'esempio di prima mi dà errore.
Riguardo il capitolo 12, paragrafo 12.8: dopo il codice c'è messo che P1 e P2 sono lo stesso punto (e questa cosa è scritta anche nel paragrafo Uguaglianza) però l'interprete stesso restituisce False (oppure 0). :confused: :confused:
http://www.python.it/doc/Howtothink/Howtothink-html-it/chap12.htm
Ho fatto qualche prova e il problema non è questo che hai detto tu. Se stampo i risultati come tuple non ci sono problemi, se li metto invece uno sotto l'altro come nell'esempio di prima mi dà errore.
In che senso stampi come tuple. Posta un esempio.
Riguardo il capitolo 12, paragrafo 12.8: dopo il codice c'è messo che P1 e P2 sono lo stesso punto (e questa cosa è scritta anche nel paragrafo Uguaglianza) però l'interprete stesso restituisce False (oppure 0). :confused: :confused:
http://www.python.it/doc/Howtothink/Howtothink-html-it/chap12.htm
Probabilmente sbagli qualcosa. Ho provato ora quel esempio e mi ritorna true, quindi funziona.
DanieleC88
16-11-2008, 19:08
Ho fatto qualche prova e il problema non è questo che hai detto tu. Se stampo i risultati come tuple non ci sono problemi, se li metto invece uno sotto l'altro come nell'esempio di prima mi dà errore.
Una cosa sono le tuple, una cosa sono le assegnazioni. ;)
~FullSyst3m~
16-11-2008, 22:16
In che senso stampi come tuple. Posta un esempio.
Ad esempio:
print uno, due, tre
Invece ad esempio
print a = b + c
mi dà errore
[QUOTE]
Probabilmente sbagli qualcosa. Ho provato ora quel esempio e mi ritorna true, quindi funziona
Non so come fa a funzionarti visto che anche nel libro ritorna 0 (cioè False)
Una cosa sono le tuple, una cosa sono le assegnazioni.
So che sono due cose diverse, ma nelle prove che ho fatto a volte anche con le tuple dava errore, per questo non mi quadra la cosa. Farò qualche altra prova ;)
DanieleC88
16-11-2008, 22:23
So che sono due cose diverse, ma nelle prove che ho fatto a volte anche con le tuple dava errore, per questo non mi quadra la cosa. Farò qualche altra prova ;)
Non so che prove tu abbia fatto, ma evidentemente l'errore era nella prova, non nella stampa delle tuple. ;)
~FullSyst3m~
16-11-2008, 22:24
Non so che prove tu abbia fatto, ma evidentemente l'errore era nella prova, non nella stampa delle tuple. ;)
Io infatti non ho detto che l'errore era nella stampa delle tuple, sto parlando di assegnazioni e stampa
DanieleC88
16-11-2008, 22:49
Allora non ho capito cos'è che non ti torna... :mbe:
Ad esempio:
print uno, due, tre
Prima di tutto questa non è una tupla. Stai semplicemente passando alla funzione print tre parametri. Per essere più precisi tre variabili che hanno tre valori ben definiti quando la funzione print viene chiamata.
Se tu volessi stampare una tupla dovresti fare:
print (1, 2, 3)
Sintassi valida anche questa ma in questo caso passi a print un singolo parametro che contiene una tupla.
print a = b + c
mi dà errore
In python l'assegnazione, una volta valutata, non ritorna alcun valore per questo motivo non può funzionare in alcun modo.
Non so come fa a funzionarti visto che anche nel libro ritorna 0 (cioè False)
Ti stai per caso riferendo a questa parte del esempio di 12.8?
P1 == P2
Se si è spiegato sotto perché ritorna false. I due punti contengono le stesse coordinate quindi sono logicamente lo stesso punto ma questo python non lo può sapere. Visto che p2 è solo una copia di p1 si tratta di due oggetti diversi e quindi viene ritornato false. La funzione StessoPunto invece conosce Punto ed esegue un confronto più corretto e quindi ritorna true.
~FullSyst3m~
17-11-2008, 07:31
Prima di tutto questa non è una tupla. Stai semplicemente passando alla funzione print tre parametri. Per essere più precisi tre variabili che hanno tre valori ben definiti quando la funzione print viene chiamata.
Se tu volessi stampare una tupla dovresti fare:
print (1, 2, 3)
Sintassi valida anche questa ma in questo caso passi a print un singolo parametro che contiene una tupla.
Ho sbagliato esempio, ecco qua:
def Muovi2(Rettangolo, dx, dy, Altezza, Larghezza):
NuovoRettangolo = copy.deepcopy(Rettangolo)
SpostaSx = NuovoRettangolo.AltoSx + dx
SpostaSy = NuovoRettangolo.AltoSy + dy
SpostaBx = NuovoRettangolo.Bx + Altezza
SpostaBy = NuovoRettangolo.By + Larghezza
return SpostaSx, SpostaSy, SpostaBx, SpostaBy
print Muovi2(R, 20, 25, 60, 65)
Prova e vedi cosa ritorna
In python l'assegnazione, una volta valutata, non ritorna alcun valore per questo motivo non può funzionare in alcun modo.
Quindi non si può stampare un'assegnazione ma si può solo ritornare il risultato dell'espressione e casomai stamparlo nel momento in cui si chiama la funzione?
Ti stai per caso riferendo a questa parte del esempio di 12.8?
P1 == P2
Se si è spiegato sotto perché ritorna false. I due punti contengono le stesse coordinate quindi sono logicamente lo stesso punto ma questo python non lo può sapere. Visto che p2 è solo una copia di p1 si tratta di due oggetti diversi e quindi viene ritornato false. La funzione StessoPunto invece conosce Punto ed esegue un confronto più corretto e quindi ritorna true.
Si mi riferivo a questo, non capivo perchè, visto che sia nel 12.8 che nel paragrafo dell'uguaglianza, visto che restituiva in tutti e due casi False nel libro c'è messo che P1 e P2 sono lo stesso punto
cdimauro
17-11-2008, 07:42
Sono di passaggio e (tanto per cambiare) ho poco tempo. Chiarisco soltanto una cosa.
Non ti fare di questi problemi. L'unico linguaggio in cui metodi e funzioni avevano un comportamento leggermente differente e richiedevano una sintassi diversa era il vecchio visual basic. Ora grazie al cielo hanno tolto questa idiozia nelle nuove versioni .net.
In linguaggi come python in cui tutto è un oggetto questa distinzione non esiste. Non mi stupirebbe affatto se python aggiungesse silenziosamente tutti i metodi definiti al di fuori di una classe ad un oggetto base tipo Kernel come fa ruby, quindi di fatto sono tutti metodi.
In ruby, dove tutto quanto è un oggetto, una funzione deve essere per forza associata ad una classe, non può esistere da sola. Quando definisci un metodo fuori da una classe l'interprete ruby invece di picchiarti chiude un occhio. Di fatto prende il tuo codice e la aggiunge a quello nella classe Kernel. Python e ruby hanno molti punti in comune quindi suppongo che anche il pitone funzioni in maniera simile ma non prendere queste cose per oro colato finche non passa cesare a darci una conferma.
No, in Python funzioni e metodi sono oggetti diversi e hanno un comportamento leggermente diverso:
>>> def f(self):
... pass
...
>>> class c:
... def f(self):
... pass
...
>>> dir (f)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals',
'func_name']
>>> dir (c.f)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex_
_', '__repr__', '__setattr__', '__str__', 'im_class', 'im_func', 'im_self']
>>> f.__class__
<type 'function'>
>>> c.f.__class__
<type 'instancemethod'>
Il punto in comune con Ruby è che anche in Python qualunque cosa è un oggetto, ma se definisci una funzione in un modulo (quindi non all'interno di una classe) hai creato un oggetto di tipo funzione e il cui binding è stato fatto nel namespace del modulo in cui è stato definito (oppure all'interno di una funzione, se si tratta di una funzione annidata).
In generale qualunque oggetto alla fine discende dalla classe object, e... tanto basta. Non c'è bisogno, quindi, per una funzione di essere necessariamente un metodo di una classe. :)
~FullSyst3m~
17-11-2008, 09:46
Sono di passaggio e (tanto per cambiare) ho poco tempo. Chiarisco soltanto una cosa.
No, in Python funzioni e metodi sono oggetti diversi e hanno un comportamento leggermente diverso:
>>> def f(self):
... pass
...
>>> class c:
... def f(self):
... pass
...
>>> dir (f)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals',
'func_name']
>>> dir (c.f)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex_
_', '__repr__', '__setattr__', '__str__', 'im_class', 'im_func', 'im_self']
>>> f.__class__
<type 'function'>
>>> c.f.__class__
<type 'instancemethod'>
Il punto in comune con Ruby è che anche in Python qualunque cosa è un oggetto, ma se definisci una funzione in un modulo (quindi non all'interno di una classe) hai creato un oggetto di tipo funzione e il cui binding è stato fatto nel namespace del modulo in cui è stato definito (oppure all'interno di una funzione, se si tratta di una funzione annidata).
In generale qualunque oggetto alla fine discende dalla classe object, e... tanto basta. Non c'è bisogno, quindi, per una funzione di essere necessariamente un metodo di una classe. :)
Non c'ho capito molto io. E oltretutto ora mi sono tornati i dubbi su metodi e funzioni
DanieleC88
17-11-2008, 18:04
Sono decisamente OT in questo momento, ma ieri ho trovato per caso questa pagina (è in inglese) (http://www.siafoo.net/article/52) e m'è venuto in mente di segnalarvela, può essere una lettura interessante per chi vuole approfondire qualche tecnica di Python. :)
DanieleC88
17-11-2008, 18:06
Non c'ho capito molto io. E oltretutto ora mi sono tornati i dubbi su metodi e funzioni
Lascia perdere per adesso, quando avrai finito di studiare a fondo le classi tornerai qui a leggere la spiegazione sulla differenza tra funzioni e metodi. Non confonderti le idee e vai avanti con le funzioni, ciò che già conosci.
~FullSyst3m~
17-11-2008, 18:21
Lascia perdere per adesso, quando avrai finito di studiare a fondo le classi tornerai qui a leggere la spiegazione sulla differenza tra funzioni e metodi. Non confonderti le idee e vai avanti con le funzioni, ciò che già conosci.
Ma io ho capito la differenza, non ho capito molto quello che ha scritto cdimauro (self, __class__ ecc non so cosa sono perchè ancora non li ho studiati).
Interessante il link, thanks ;)
MasterDany
17-11-2008, 19:12
e arrivo io con le domande idiote!:D
http://www.python.it/doc/Howtothink/Howtothink-html-it/chap02.htm
sul paragrafo 2.8
Riesci ad immaginare una proprietà che somma e moltiplicazione tra numeri non condividono con concatenamento e ripetizione di stringhe?
a quali proprietà si riferisce?
~FullSyst3m~
17-11-2008, 19:18
e arrivo io con le domande idiote!:D
http://www.python.it/doc/Howtothink/Howtothink-html-it/chap02.htm
sul paragrafo 2.8
a quali proprietà si riferisce?
Si riferisce semplicemente a quello che hai studiato sul libro ;). In ogni caso guarda tra le prima pagine che c'è scritto a cosa si riferisce
MasterDany
17-11-2008, 19:20
il punto è che non riesco a capire il senso della domanda!
Soluzione?
~FullSyst3m~
17-11-2008, 19:23
il punto è che non riesco a capire il senso della domanda!
Soluzione?
Te l'ho detto, rileggiti le prime pagine. Avevo lo stesso dubbio pure io
MasterDany
17-11-2008, 19:23
quali pagine?? :mc:
MasterDany
17-11-2008, 19:45
Te l'ho detto, rileggiti le prime pagine. Avevo lo stesso dubbio pure io
le prime pagine...numeri?? paragrafi??
~FullSyst3m~
17-11-2008, 20:03
le prime pagine...numeri?? paragrafi??
Le prime pagine del topic non del libro
MasterDany
17-11-2008, 20:31
non trovo...:mc:
~FullSyst3m~
17-11-2008, 21:54
non trovo...:mc:
Inizia dal primo post e leggi, è all'inizio
~FullSyst3m~
18-11-2008, 10:01
Esercizio del primo paragrafo del capitolo 13:
class Tempo:
pass
Time = Tempo()
Time.ore = 10
Time.minuti = 26
Time.secondi = 0
def StampaTempo (Tempo):
print "Sono le ore", Time.ore, ":", Time.minuti, ":", Time.secondi
StampaTempo (Time)
L'unico problema è che invece di visualizzarmi 00 i secondi me li visualizza con uno zero solo.
Inoltre vorrei un parere sul secondo esercizio, cosi per vedere se ragiono un pò in modo corretto :D
class Tempo:
pass
Time = Tempo()
Time.ore = 10
Time.minuti = 26
Time.secondi = 22
Time2 = Tempo()
Time2.ore = 12
Time2.minuti = 36
Time2.secondi = 43
def Dopo (Tempo, Tempo2):
return (Tempo.ore > Tempo.ore) and (Tempo.minuti > Tempo.minuti)
print Dopo(Time, Time2)
DanieleC88
18-11-2008, 10:16
L'unico problema è che invece di visualizzarmi 00 i secondi me li visualizza con uno zero solo.
Perché non ti basta stamparlo: numericamente è 0, ha ragione Python... Devi usare una stringa di formato. :)
def Dopo (Tempo, Tempo2):
return (Tempo.ore > Tempo.ore) and (Tempo.minuti > Tempo.minuti)
Hmm... e se gli passi due tempi che differiscono solo di secondi?
def Dopo (Tempo, Tempo2):
return (Tempo.ore > Tempo.ore) and (Tempo.minuti > Tempo.minuti)
Sicuro di non esserti scordato qualcosa? Perché così questo return è sempre falso.
~FullSyst3m~
18-11-2008, 11:49
Perché non ti basta stamparlo: numericamente è 0, ha ragione Python... Devi usare una stringa di formato. :)
Hmm... e se gli passi due tempi che differiscono solo di secondi?
Veramente si potrebbe fare anche solo con le ore per vedere se uno è più avanti o uno più indietro. Se poi le ore sono le stesse si fa cosi con i minuti e in caso con i secondi
Comunque hai ragione, non c'avevo pensato, devo convertire in stringa con str oppure usare "%d" :D
Sicuro di non esserti scordato qualcosa? Perché così questo return è sempre falso.
Azz, ho scritto due riferimenti uguali. C'è il mio capo che ogni volta mi trova a studiare e si incazza come una iena :D
def Dopo (Tempo, Tempo2):
return (Tempo.ore > Tempo2.ore) and (Tempo.minuti > Tempo2.minuti)
Anche cosi però ha qualche bug, se ad esempio le ore sono maggiori, ma i minuti minori ritorna False. Devo migliorarlo ancora un pò
~FullSyst3m~
18-11-2008, 11:57
L'ho appena scritto:
class Tempo:
pass
Time = Tempo()
Time.ore = 13
Time.minuti = 26
Time.secondi = 22
Time2 = Tempo()
Time2.ore = 12
Time2.minuti = 36
Time2.secondi = 43
def Dopo (Tempo, Tempo2):
if Tempo.ore > Tempo2.ore:
return True
if (Tempo.ore == Tempo2.ore) and (Tempo.minuti > Tempo2.minuti):
return True
elif (Tempo.ore == Tempo2.ore) and (Tempo.minuti == Tempo2.minuti) and (Tempo.secondi > Tempo2.secondi):
return True
else:
return False
print Dopo(Time, Time2)
Non ho inserito il caso che i due tempi sono uguali (ho la pasta nel piatto), ma ho fatto due prove e sembra funzionare. Ma sicuramente è troppo lungo e si può ancora ottimizzare
Non ho inserito il caso che i due tempi sono uguali (ho la pasta nel piatto), ma ho fatto due prove e sembra funzionare. Ma sicuramente è troppo lungo e si può ancora ottimizzare
Fa piacere vedere che stai cominciando a capire come si ragiona. Quando dici che è troppo lungo hai ragione, può essere semplificato e riscritto in 3 righe. Piccolo suggerimento, lascia perdere ore, minuti e trasforma tutto quanto in secondi.
DanieleC88
18-11-2008, 13:35
Sicuro di non esserti scordato qualcosa? Perché così questo return è sempre falso.
Oddio è vero! :asd:
/me si ritira nell'angolino buio
~FullSyst3m~
18-11-2008, 14:45
Fa piacere vedere che stai cominciando a capire come si ragiona. Quando dici che è troppo lungo hai ragione, può essere semplificato e riscritto in 3 righe. Piccolo suggerimento, lascia perdere ore, minuti e trasforma tutto quanto in secondi.
Io mi sono basato su quello che chiedeva il testo per questo l'ho fatto con ore, minuti e secondi
MasterDany
18-11-2008, 15:04
Ancora niente!Sono arrivato fino a pagina 5 :muro:
eppoi il post parte dal capitolo 3 quella è del capitolo 2
~FullSyst3m~
18-11-2008, 15:49
Ho provato a fare quello che mi hai suggerito, ho abbozzato questo codice, si potrebbe pure togliere la funzione Dopo e incapsulare il tutto in SommaSecondi (cambiando il nome magari). Oppure creare una funzione che converte in secondi e una che somma i secondi e fa il confronto
class Tempo:
pass
Time = Tempo()
Time.secondi = 46800 #ore 13
Time.secondi2 = 1560 #26 minuti
Time.secondi3 = 22
Time2 = Tempo()
Time2.secondi = 43200 #ore 12
Time2.secondi2 = 2160 #36 minuti
Time2.secondi3 = 43
def SommaSecondi (Tempo1, Tempo2):
Somma = Tempo()
Somma.uno = Tempo1.secondi + Tempo1.secondi2 + Tempo1.secondi3
Somma.due = Tempo2.secondi + Tempo2.secondi2 + Tempo2.secondi3
if Somma.uno > Somma.due:
return True
else:
return False
def Dopo (Tempo1, Tempo2):
return SommaSecondi(Tempo1, Tempo2)
print Dopo(Time, Time2)
~FullSyst3m~
18-11-2008, 15:56
Ancora niente!Sono arrivato fino a pagina 5 :muro:
eppoi il post parte dal capitolo 3 quella è del capitolo 2
Non sono scritti in ordine i capitoli, guarda che deve essere lì
MasterDany
18-11-2008, 16:09
non lo trovo ancora...chi mi aiuta?
MasterDany
18-11-2008, 16:35
Come avrete capito sto leggendo anche io questo libro.Sto al capitolo 3 cercando di comprendere le funzioni matematiche.Faccio il primo superiore coseno,seno,logaritmi(questi li conosco un po',non so le varie proprietaò ma so cosa sono) non so dove mettergli mano.Cosi mi sono andato a vedere su internet(soprattutto su wikipedia) cosa sono.Faccio bene?
Oppure potrei anche tralasciarli?
Ricordate che sto studiando python per provare a creare piccoli giochini! :cool:
class Tempo:
pass
Time = Tempo()
Time.secondi = 46800 #ore 13
Time.secondi2 = 1560 #26 minuti
Time.secondi3 = 22
Time2 = Tempo()
Time2.secondi = 43200 #ore 12
Time2.secondi2 = 2160 #36 minuti
Time2.secondi3 = 43
La classe Time andava bene ed era fatta come ti chiedeva l'esercizio non dovevi toccarla. Quei tre campi secondi sono orrendi, non fare mai più una cosa simile.
def SommaSecondi (Tempo1, Tempo2):
Somma = Tempo()
Somma.uno = Tempo1.secondi + Tempo1.secondi2 + Tempo1.secondi3
Somma.due = Tempo2.secondi + Tempo2.secondi2 + Tempo2.secondi3
if Somma.uno > Somma.due:
return True
else:
return False
Perché crei un nuovo oggetto tempo per calcolare la somma dei secondi? Non basta usare due variabili temporanee? La conversione da ore a secondi e da minuti a secondi andava fatta qui al volo e non a mano nel codice qui sopra. Altro errore e fare il confronto in una funzione che si chiama SommaSecondi. Le funzioni devono fare solo quello che dice il nome e niente più. Quel if poi serve veramente non puoi usare direttamente il return?
def Dopo (Tempo1, Tempo2):
return SommaSecondi(Tempo1, Tempo2)
print Dopo(Time, Time2)
La funzione inutile è SommaSecondi ed è quella che va eliminata.
~FullSyst3m~
18-11-2008, 16:40
Come avrete capito sto leggendo anche io questo libro.Sto al capitolo 3 cercando di comprendere le funzioni matematiche.Faccio il primo superiore coseno,seno,logaritmi(questi li conosco un po',non so le varie proprietaò ma so cosa sono) non so dove mettergli mano.Cosi mi sono andato a vedere su internet(soprattutto su wikipedia) cosa sono.Faccio bene?
Oppure potrei anche tralasciarli?
Ricordate che sto studiando python per provare a creare piccoli giochini! :cool:
Il post ormai è abbastanza grande, fai una ricerca che trovi subito il messaggio. Per il resto fai bene a cercare, è una buona abitudine, ma se ancora quelle cose non le hai fatte le puoi tralasciare, l'importante capire il concetto e l'argomento che studi ;)
~FullSyst3m~
18-11-2008, 16:44
La classe Time andava bene ed era fatta come ti chiedeva l'esercizio non dovevi toccarla. Quei tre campi secondi sono orrendi, non fare mai più una cosa simile.
Perché crei un nuovo oggetto tempo per calcolare la somma dei secondi? Non basta usare due variabili temporanee? La conversione da ore a secondi e da minuti a secondi andava fatta qui al volo e non a mano nel codice qui sopra. Altro errore e fare il confronto in una funzione che si chiama SommaSecondi. Le funzioni devono fare solo quello che dice il nome e niente più. Quel if poi serve veramente non puoi usare direttamente il return?
La funzione inutile è SommaSecondi ed è quella che va eliminata.
Sono a lavoro, però quando ho scritto mi rendevo conto che erano una cosa orrenda quegli attributi.
Potevo usare direttamente return, ma il confronto dovevo farlo per vedere se era maggiore o no.
Hai ragione, la prima cosa che avevo pensato era modificare Dopo, però poi ho voluto sperimentare un pò e ho scritto quel codice, che mi rendo conto che fa proprio schifo. Quando ho un minuto libero lo modifico
~FullSyst3m~
18-11-2008, 17:06
Perché non ti basta stamparlo: numericamente è 0, ha ragione Python... Devi usare una stringa di formato. :)
Hmm... e se gli passi due tempi che differiscono solo di secondi?
Anche usando la stringa di formato comunque mi stampa sempre 0 invece di 00
~FullSyst3m~
18-11-2008, 17:10
Ecco qua un'altra bozza molto più concisa:
class Tempo:
pass
Time = Tempo()
Time.ore = 1
Time.minuti = 32
Time.secondi = 22
Time2 = Tempo()
Time2.ore = 1
Time2.minuti = 30
Time2.secondi = 43
def Dopo (Tempo1, Tempo2):
OreMinutiSecondi = (Tempo1.ore * 60 * 60) + (Tempo1.minuti * 60)
OreMinutiSecondi2 = (Tempo2.ore * 60 * 60) + (Tempo2.minuti * 60)
return OreMinutiSecondi > OreMinutiSecondi2
print Dopo(Time, Time2)
Ora torno al lavoro altrimenti il mio capo mi licenzia :D
DanieleC88
18-11-2008, 17:13
Anche usando la stringa di formato comunque mi stampa sempre 0 invece di 00
[jmc@mordor ~]$ python
Python 2.6 (r26:66714, Oct 27 2008, 10:50:31)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print "Due zeri invece di uno: %.02d" % (0)
Due zeri invece di uno: 00
>>>
MasterDany
18-11-2008, 17:44
Non riesco ancora a trovalo su cerca ,il motore di ricerca non mifunziona,cosi mi rimane una pagina bianca.Non fate prima a riscere la soluzione? :O
Ecco qua un'altra bozza molto più concisa:
class Tempo:
pass
Time = Tempo()
Time.ore = 1
Time.minuti = 32
Time.secondi = 22
Time2 = Tempo()
Time2.ore = 1
Time2.minuti = 30
Time2.secondi = 43
def Dopo (Tempo1, Tempo2):
OreMinutiSecondi = (Tempo1.ore * 60 * 60) + (Tempo1.minuti * 60)
OreMinutiSecondi2 = (Tempo2.ore * 60 * 60) + (Tempo2.minuti * 60)
return OreMinutiSecondi > OreMinutiSecondi2
print Dopo(Time, Time2)
Ora torno al lavoro altrimenti il mio capo mi licenzia :D
Ti sei scordato di nuovo di aggiungere i secondi ma non importa, alla fine sei giunto alla soluzione migliore. :mano:
Non riesco ancora a trovalo su cerca ,il motore di ricerca non mifunziona,cosi mi rimane una pagina bianca.Non fate prima a riscere la soluzione? :O
Soluzione a cosa? Hai detto che hai problemi con il capitolo 3, ma quale paragrafo non ti è chiaro? Quali sono precisamente questi problemi? Sei stato piuttosto generico e si fa fatica a risponderti.
~FullSyst3m~
18-11-2008, 19:01
Ti sei scordato di nuovo di aggiungere i secondi ma non importa, alla fine sei giunto alla soluzione migliore. :mano:
Li ho tralasciati di mia volontà, stava tornando il capo e poi faceva casino :muro:
~FullSyst3m~
18-11-2008, 19:03
[jmc@mordor ~]$ python
Python 2.6 (r26:66714, Oct 27 2008, 10:50:31)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print "Due zeri invece di uno: %.02d" % (0)
Due zeri invece di uno: 00
>>>
Perchè 02? Comunque:
class Tempo:
pass
Time = Tempo()
Time.ore = 10
Time.minuti = 26
Time.secondi = 00
Time2 = Tempo()
Time2.ore = 12
Time2.minuti = 36
Time2.secondi = 00
def StampaTempo (Tempo):
print "Sono le ore", Tempo.ore, ":", Tempo.minuti, ":", "%d" % Tempo.secondi
Mi stampa sempre 0
MasterDany
18-11-2008, 20:33
questo post:
http://www.hwupgrade.it/forum/showpost.php?p=25056270&postcount=419
e arrivo io con le domande idiote!:D
http://www.python.it/doc/Howtothink/Howtothink-html-it/chap02.htm
sul paragrafo 2.8
a quali proprietà si riferisce?
Così su due piedi direi distributiva per la moltiplicazione e commutativa per la somma.
~FullSyst3m~
18-11-2008, 22:12
Così su due piedi direi distributiva per la moltiplicazione e commutativa per la somma.
Anche io avevo pensato questo quando avevo iniziato a studiare il libro, ma poi cdimauro mi ha detto che in pratica si riferiva semplicemente a quello che dice il libro, ad esempio che 1 * 4 = 4, ma "Pippo" * 4 = Pippo Pippo Pippo Pippo
~FullSyst3m~
19-11-2008, 09:02
Perchè 02? Comunque:
class Tempo:
pass
Time = Tempo()
Time.ore = 10
Time.minuti = 26
Time.secondi = 00
Time2 = Tempo()
Time2.ore = 12
Time2.minuti = 36
Time2.secondi = 00
def StampaTempo (Tempo):
print "Sono le ore", Tempo.ore, ":", Tempo.minuti, ":", "%d" % Tempo.secondi
Mi stampa sempre 0
Mettendo 02 invece mi stampa i due 0, ma non capisco perchè. Sul libro c'è messo che il numero dopo il % serve per scegliere quandi caratteri si devono stampare, ma provando con 2 mi stampa sempre uno 0 soltanto :confused:
~FullSyst3m~
19-11-2008, 09:24
L'esercizio del 13.3, cioè riscrivere la funzione Incremento senza usare nessun ciclo, come è possibile farlo? Apparte con if non mi viene altra soluzione in mente al momento
DanieleC88
19-11-2008, 10:28
Mettendo 02 invece mi stampa i due 0, ma non capisco perchè. Sul libro c'è messo che il numero dopo il % serve per scegliere quandi caratteri si devono stampare, ma provando con 2 mi stampa sempre uno 0 soltanto :confused:
Perché con %2d gli stai dicendo di usare un formato lungo due spazi, allineando il numero sulla destra (gli spazi in eccesso li stampa a sinistra). Con %02d invece gli dici la stessa cosa, ma in più gli indichi di sostituire gli spazi in eccesso con degli zeri.
DanieleC88
19-11-2008, 10:29
L'esercizio del 13.3, cioè riscrivere la funzione Incremento senza usare nessun ciclo, come è possibile farlo? Apparte con if non mi viene altra soluzione in mente al momento
Posta il testo del problema, vediamo.
~FullSyst3m~
19-11-2008, 10:31
Perché con %2d gli stai dicendo di usare un formato lungo due spazi, allineando il numero sulla destra (gli spazi in eccesso li stampa a sinistra). Con %02d invece gli dici la stessa cosa, ma in più gli indichi di sostituire gli spazi in eccesso con degli zeri.
Questa cosa non la sapevo, allora si può scegliere anche con cosa riempire gli spazi.. sul libro non dice nulla a riguardo. Uff, mancano un pò di cose in questo libro.
Riguardo l'esercizio di prima comunque, una soluzione migliore del while non mi viene in mente al momento. A me sembra buona come soluzione
Questa cosa non la sapevo, allora si può scegliere anche con cosa riempire gli spazi.. sul libro non dice nulla a riguardo. Uff, mancano un pò di cose in questo libro.
SI tratta di un libro introduttivo, non ha le pretesi di spiegarti ogni aspetto di python e poi queste stringhe di formato sono ereditate dal C e non è che siano il massimo come chiarezza.
Riguardo l'esercizio di prima comunque, una soluzione migliore del while non mi viene in mente al momento. A me sembra buona come soluzione
Divisione, somma e sottrazione. Parti dalle ore. ;)
variabilepippo
19-11-2008, 11:01
Uff, mancano un pò di cose in questo libro.
Nessun libro è completo, infatti questo libro sarà soltanto il primo di una lunga serie (spero per te)! ;)
Considera che se vuoi approfondire gli argomenti che studi sul libro devi consultare spesso la documentazione ufficiale (http://www.python.org/doc/) per scoprire ciò che non può essere riportato su un testo cartaceo. Per esempio le operazioni di formattazione delle stringhe sono descritte in questa pagina (http://www.python.org/doc/2.5.2/lib/typesseq-strings.html) della documentazione.
~FullSyst3m~
19-11-2008, 11:47
SI tratta di un libro introduttivo, non ha le pretesi di spiegarti ogni aspetto di python e poi queste stringhe di formato sono ereditate dal C e non è che siano il massimo come chiarezza.
Divisione, somma e sottrazione. Parti dalle ore. ;)
Con il while non è più comodo (e più corto)?
Nessun libro è completo, infatti questo libro sarà soltanto il primo di una lunga serie (spero per te)!
Considera che se vuoi approfondire gli argomenti che studi sul libro devi consultare spesso la documentazione ufficiale per scoprire ciò che non può essere riportato su un testo cartaceo. Per esempio le operazioni di formattazione delle stringhe sono descritte in questa pagina della documentazione.
Infatti, però dico solo che essendo cose che mettono loro stessi almeno questo potevano scriverlo, ma va bene cosi dai ;) Comunque c'è anche da studiare inglese e bene pure, altrimenti non è facile capire la documentazione ufficiale
Mentre ho fatto il secondo esercizio del 13.3, ditemi qualche parere:
class Tempo:
pass
Time = Tempo()
Time.ore = 10
Time.minuti = 26
Time.secondi = 00
Time2 = Tempo()
Time2.ore = 12
Time2.minuti = 36
Time2.secondi = 00
def IncrementoPuro (T, Secondi):
NuovoTempo = Tempo()
NuovoTempo.secondi = T.secondi + Secondi
NuovoTempo.minuti = T.minuti
Somma.ore = T.ore
while NuovoTempo.secondi >= 60:
NuovoTempo.secondi = Somma.secondi - 60
NuovoTempo.minuti = T.minuti + 1
while T.minuti >= 60:
NuovoTempo.minuti = T.minuti - 60
NuovoTempo.ore = T.ore + 1
return NuovoTempo.secondi, NuovoTempo.minuti, NuovoTempo.ore
Con il while non è più comodo (e più corto)?
Senza dubbio è più intuitivo ma è più lungo e per valori molti grandi è anche più lento perché ti metti a fare centinaia di cicli per ogni incremento. Piccolo aiuto.
Se hai 123 Secondi e dividi per 60 ottieni 2 resto 3. Il quoziente è il numero da aggiungere a minuti mentre il resto sono i secondi che rimangono. Applica lo steso principio anche a minuti e risolvi tutto quanto in poche righe di codice che funzionano in tutti i casi
Mentre ho fatto il secondo esercizio del 13.3, ditemi qualche parere:
class Tempo:
pass
Time = Tempo()
Time.ore = 10
Time.minuti = 26
Time.secondi = 00
Time2 = Tempo()
Time2.ore = 12
Time2.minuti = 36
Time2.secondi = 00
def IncrementoPuro (T, Secondi):
NuovoTempo = Tempo()
NuovoTempo.secondi = T.secondi + Secondi
NuovoTempo.minuti = T.minuti
Somma.ore = T.ore
while NuovoTempo.secondi >= 60:
NuovoTempo.secondi = Somma.secondi - 60
NuovoTempo.minuti = T.minuti + 1
while T.minuti >= 60:
NuovoTempo.minuti = T.minuti - 60
NuovoTempo.ore = T.ore + 1
return NuovoTempo.secondi, NuovoTempo.minuti, NuovoTempo.ore
Perché non ritorni direttamente l'oggetto NuovoTempo?
~FullSyst3m~
19-11-2008, 13:43
Senza dubbio è più intuitivo ma è più lungo e per valori molti grandi è anche più lento perché ti metti a fare centinaia di cicli per ogni incremento. Piccolo aiuto.
Se hai 123 Secondi e dividi per 60 ottieni 2 resto 3. Il quoziente è il numero da aggiungere a minuti mentre il resto sono i secondi che rimangono. Applica lo steso principio anche a minuti e risolvi tutto quanto in poche righe di codice che funzionano in tutti i casi
Grazie dell'aiuto, ma lo avevo già scritto, eccolo qua:
Minuti_temp = (Tempo.Secondi + Secondi) / 60
Tempo.Secondi = (Tempo.Secondi + Secondi )- 60*Minuti_temp
Tempo.Minuti = Tempo.Minuti + Minuti_temp
Comunque se non era per il primo aiuto non ci arrivavo, non avrei pensato a questa soluzione anche se il while era buona, ma non la migliore. Mi sento un idiota quando non penso a queste cose banali. Anche con i numeri casuali ricordi? Può essere che questo sia dovuto alle mie lacune in matematica?
Perché non ritorni direttamente l'oggetto NuovoTempo?
Perchè stavo provando a fare una cosa per vedere se i risultati erano ok. Era in fase di test :D
AnonimoVeneziano
19-11-2008, 14:36
Grazie dell'aiuto, ma lo avevo già scritto, eccolo qua:
Minuti_temp = (Tempo.Secondi + Secondi) / 60
Tempo.Secondi = (Tempo.Secondi + Secondi )- 60*Minuti_temp
Tempo.Minuti = Tempo.Minuti + Minuti_temp
Comunque se non era per il primo aiuto non ci arrivavo, non avrei pensato a questa soluzione anche se il while era buona, ma non la migliore. Mi sento un idiota quando non penso a queste cose banali. Anche con i numeri casuali ricordi? Può essere che questo sia dovuto alle mie lacune in matematica?
Se ho capito bene quello che fa la funzione (ossia incrementare ore, minuti e secondi dell'oggetto Tempo in base al numero "grezzo" di secondi fornito come parametro) questo codice dovrebbe essere quello che fa quello che vuoi senza while di sorta
def Incremento(T, Secondi):
NuovoTempo = Tempo()
NuovoTempo.secondi = T.secondi
NuovoTempo.minuti = T.minuti
NuovoTempo.ore = T.ore
NuovoTempo.minuti += (NuovoTempo.secondi + Secondi) / 60
NuovoTempo.secondi = (NuovoTempo.secondi + Secondi) % 60
NuovoTempo.ore += NuovoTempo.minuti / 60
NuovoTempo.minuti = NuovoTempo.minuti % 60
return NuovoTempo
Ciao
~FullSyst3m~
19-11-2008, 17:48
Se ho capito bene quello che fa la funzione (ossia incrementare ore, minuti e secondi dell'oggetto Tempo in base al numero "grezzo" di secondi fornito come parametro) questo codice dovrebbe essere quello che fa quello che vuoi senza while di sorta
def Incremento(T, Secondi):
NuovoTempo = Tempo()
NuovoTempo.secondi = T.secondi
NuovoTempo.minuti = T.minuti
NuovoTempo.ore = T.ore
NuovoTempo.minuti += (NuovoTempo.secondi + Secondi) / 60
NuovoTempo.secondi = (NuovoTempo.secondi + Secondi) % 60
NuovoTempo.ore += NuovoTempo.minuti / 60
NuovoTempo.minuti = NuovoTempo.minuti % 60
return NuovoTempo
Ciao
Si la funzione vuole questo, ma il += cosa incrementa? E il codice che avevo scritto io non era buono?
Si la funzione vuole questo, ma il += cosa incrementa? E il codice che avevo scritto io non era buono?
La variabile alla sua sinistra. Quando vedi una sintassi simile:
a += 1
Devi pensarla scritta in questo modo:
a = a + 1
Si tratta di una scorciatoia per non scrivere due volte "a" e funziona anche con altri operatori come -, * e /
~FullSyst3m~
19-11-2008, 19:09
La variabile alla sua sinistra. Quando vedi una sintassi simile:
a += 1
Devi pensarla scritta in questo modo:
a = a + 1
Si tratta di una scorciatoia per non scrivere due volte "a" e funziona anche con altri operatori come -, * e /
Allora è come pensavo perchè vedendo i vari codici scritti c'era sempre questa cosa in comune, però non ne avevo la certezza visto che il libro tratta la sintassi "estesa".
R1.AltoSinistra.x = 0.0;
R1.AltoSinistra.y = 0.0;
Come mai c'è il ; finale?
AnonimoVeneziano
19-11-2008, 19:21
R1.AltoSinistra.x = 0.0;
R1.AltoSinistra.y = 0.0;
Come mai c'è il ; finale?
Questo o è C o C++ o Java
AnonimoVeneziano
19-11-2008, 19:26
E il codice che avevo scritto io non era buono?
Mmm, a dire il vero non avevo visto quel post.
Comunque l'uso dell'operatore "%" è più conciso , comunque a prima vista il tuo codice dovrebbe andare bene :p
DanieleC88
19-11-2008, 19:27
O è Python e gli è semplicemente sfuggito... Se usi il punto e virgola puoi inserire più istruzioni sulla stessa riga:
istruzione1; istruzione2
Se invece si scrive questo:
istruzione1;
è come aver inserito una riga vuota dopo la prima istruzione... semplicemente non cambia niente.
~FullSyst3m~
19-11-2008, 19:48
Questo o è C o C++ o Java
E' Python, è scritto sul libro che sto studiando
Mmm, a dire il vero non avevo visto quel post.
Comunque l'uso dell'operatore "%" è più conciso , comunque a prima vista il tuo codice dovrebbe andare bene
In che senso è più conciso?
O è Python e gli è semplicemente sfuggito... Se usi il punto e virgola puoi inserire più istruzioni sulla stessa riga:
Infatti, gli è sfuggito. Comunque buono a sapersi, per cultura personale ;)
cdimauro
20-11-2008, 07:25
Quei ; si possono usare anche in Python, come ha spiegato Daniele, ma scrivere codice così non è assolutamente "pythonic": evitali come la peste.
Per quanto riguarda il %, è più coinciso rispetto a C & derivati perché è più semplice e immediato l'utilizzo.
Infine per il tuo esercizio con le date, io avrei ridefinito i metodi __str__ (per "visualizzare l'oggetto" in maniera più elegante) e __cmp__ per effettuare i confronti.
Nel primo caso ti sarebbe bastato un semplice e più chiaro:
print Tempo
per stampare l'oggetto.
Nel secondo caso per effettuare il confronto di due oggetti di tipo tempo sarebbe bastato un banale:
Tempo1 < Tempo2
Per adesso è tutto. Scusate, ma ho nuovamente poco tempo in questo periodo.
~FullSyst3m~
20-11-2008, 07:48
Potresti farmi vedere il codice? Io non li ho fatti __str__ e __cmp__, sul libro non sono spiegati ancora
Potresti farmi vedere il codice? Io non li ho fatti __str__ e __cmp__, sul libro non sono spiegati ancora
Non ti preoccupare, sono spiegati nel capitolo 14 e 15 assieme a tutti gli altri.
~FullSyst3m~
20-11-2008, 10:04
Non ti preoccupare, sono spiegati nel capitolo 14 e 15 assieme a tutti gli altri.
Si infatti, sono un pò più avanti. Entro stamattina dovrei finire il capitolo 13, sto facendo lo sviluppo pianificato adesso
~FullSyst3m~
20-11-2008, 10:38
Esercizio del 13.5:
def IncrementoPianificato(Tempo, Secondi):
Secondi = ConverteInSecondi(Tempo) + secondi
return ConverteInTempo (Secondi)
Credo sia giusto cosi
cdimauro
21-11-2008, 19:12
Non ti preoccupare, sono spiegati nel capitolo 14 e 15 assieme a tutti gli altri.
Si infatti, sono un pò più avanti. Entro stamattina dovrei finire il capitolo 13, sto facendo lo sviluppo pianificato adesso
Oops. Scusate. E' la forza dell'abitudine. :p
Esercizio del 13.5:
def IncrementoPianificato(Tempo, Secondi):
Secondi = ConverteInSecondi(Tempo) + secondi
return ConverteInTempo (Secondi)
Credo sia giusto cosi
Se ConverteInSecondi e ConverteInTempo fanno il lavoro che dicono, la risposta è sì. ;)
~FullSyst3m~
21-11-2008, 22:43
Oops. Scusate. E' la forza dell'abitudine. :p
Se ConverteInSecondi e ConverteInTempo fanno il lavoro che dicono, la risposta è sì. ;)
Il codice di ConverteInSecondi e ConverteInTempo sono sul libro e testandoli sembrano ok, quindi direi che fanno il loro lavoro ;)
P.S: nel capitolo 14, nella funzione StampaTempo non ci sono le \ per spezzare la riga di codice, nel codice più sotto invece si. Come mai questa differenza?
cdimauro
21-11-2008, 22:51
Penso sia un errore. La versione corretta è quella con i \
~FullSyst3m~
22-11-2008, 12:42
Penso sia un errore. La versione corretta è quella con i \
Eh infatti
MasterDany
23-11-2008, 20:45
Nel quarto capitolo paragrafo 4.1:
Inoltre può essere usato per estrarre la cifra più a destra di un numero: x%10 restituisce la cifra più a destra in base 10. Allo stesso modo x%100 restituisce le ultime due cifre.
cosa significa?
DanieleC88
23-11-2008, 20:57
Che se hai un numero in base 10 puoi usare quella scrittura per ottenere il valore della cifra più a destra. Ad esempio:
x = 123
print (x % 10)
ti stamperà 3 in output, che è esattamente l'ultima cifra in base 10.
Puoi fermarti anche qui per utilizzarlo negli esercizi proposti dal libro, ma se sei curioso continua a leggere. Si tratta dell'operatore modulo: divide il primo operando per il secondo e ti restituisce il resto della divisione, invece che il quoziente. Matematicamente, se hai due numeri x ed y, calcoli il valore x / y, azzeri la parte intera, e moltiplichi per y il numero decimale ottenuto: otterrai il resto della divisione. Puoi anche ripetutamente sottrarre y ad x finché non ottieni un numero minore di y, a quel punto avrai il resto finale.
ciao ;)
MasterDany
23-11-2008, 21:01
Sul capitolo 4 paragrafo 4.3 non capisco una cosa:
x=5
x and 1
Perchè questa espressione ha il valore di uno...La tavola di verità l'ho capita visto che l'ho studiata anche in algebra...In algebra funziona cosi:
a:"Marco va a scuola" a=V
b:"Marco studia" a=F
avb=Marco va a scuola e studia a=F
Quindi significa e e qui dovrebbe riportare
5 1
DanieleC88
23-11-2008, 21:13
In realtà convenzionalmente dovrebbe restituirti un valore diverso da zero se e solo se entrambi gli operandi sono diversi da zero. Python tratta i connettivi booleani in modo un po' diverso da come sono utilizzati in logica matematica: se il primo operando dell'and è valutato come vero, Python restituisce il secondo (se è vero anche lui lo è l'intera espressione, in tutti gli altri casi è falsa). L'or funziona al contrario, ma con un ragionamento molto simile.
~FullSyst3m~
23-11-2008, 22:12
Esatto, Python ragiona in un modo un pò diverso, proprio come ha detto Daniele, ma se ci ragioni non è cosi male come dicono alcuni ;)
In realtà convenzionalmente dovrebbe restituirti un valore diverso da zero se e solo se entrambi gli operandi sono diversi da zero. Python tratta i connettivi booleani in modo un po' diverso da come sono utilizzati in logica matematica: se il primo operando dell'and è valutato come vero, Python restituisce il secondo (se è vero anche lui lo è l'intera espressione, in tutti gli altri casi è falsa). L'or funziona al contrario, ma con un ragionamento molto simile.
Attenzione. L'operatore "&" non è quello logico ma quello binario. Ritorna uno perché in binario "1" ha un solo bit ad uno e quindi azzera tutti gli altri.
~FullSyst3m~
23-11-2008, 22:19
Attenzione. L'operatore "&" non è quello logico ma quello binario. Ritorna uno perché in binario "1" ha un solo bit ad uno e quindi azzera tutti gli altri.
Cioè?
Cioè?
L'operatore che intendeva Daniele è "and".
print 7 and 14
print 14 and 7
La prima riga stampa 14 mentre la seconda stampa 7. Mentre se al primo argomento c'è una valore che python interpreta come falso. Allora stampa il primo valore. Questo ad esempio stampa 0.
print 0 and 7
L'and binario prende la rappresentazione binaria dei due numeri in questione ed esegue un and bit a bit. Il numero 7 in binario è "0111" mentre 14 è "1110". Fare l'operazione in colonna è piuttosto semplice.
1110 and
0111 =
----------
0110
Quindi 14 & 7 che è qui sopra stampa 6.
DanieleC88
23-11-2008, 22:31
Attenzione. L'operatore "&" non è quello logico ma quello binario. Ritorna uno perché in binario "1" ha un solo bit ad uno e quindi azzera tutti gli altri.
Sì, ma VICIUS, se rileggi il post la domanda è sull'and logico (e io su quello ho risposto), non sul & bitwise. ;)
Per gli altri, se avete dubbi guardatene direttamente il funzionamento:
[jmc@mordor ~]$ python
Python 2.6 (r26:66714, Oct 27 2008, 10:50:31)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 6 and 2
2
>>> 8 and 2
2
>>> 8 and 1
1
>>> 6 & 2
2
>>> 8 & 2
0
>>> 8 & 1
0
DanieleC88
23-11-2008, 22:33
D'oh c'ho messo troppo tempo! :p
Sì, ma VICIUS, se rileggi il post la domanda è sull'and logico (e io su quello ho risposto), non sul & bitwise. ;)
Hai ragione. Dovrei andare a dormire invece di stare qui sul forum. Sono praticamente fuso :muro:
DanieleC88
23-11-2008, 22:36
Idem... ma tranquillo, almeno è stata una buona occasione per chiarire il funzionamento dei due operatori. :D
~FullSyst3m~
23-11-2008, 22:39
L'operatore che intendeva Daniele è "and".
print 7 and 14
print 14 and 7
La prima riga stampa 14 mentre la seconda stampa 7. Mentre se al primo argomento c'è una valore che python interpreta come falso. Allora stampa il primo valore. Questo ad esempio stampa 0.
print 0 and 7
L'and binario prende la rappresentazione binaria dei due numeri in questione ed esegue un and bit a bit. Il numero 7 in binario è "0111" mentre 14 è "1110". Fare l'operazione in colonna è piuttosto semplice.
1110 and
0111 =
----------
0110
Quindi 14 & 7 che è qui sopra stampa 6.
Si questo lo so, come ha detto Daniele, parlavamo dell'and logico non bitwise. Il cioè era riferito al bitwise perchè non la sapevo questa cosa dell'&.
>>> 6 & 2
2
>>> 8 & 2
0
>>> 8 & 1
0
Restituisce questi risultati sempre per il procedimento che ha scritto VICIUS?
DanieleC88
23-11-2008, 22:44
Restituisce questi risultati sempre per il procedimento che ha scritto VICIUS?
Ovviamente sì, confronta i risultati calcolatrice alla mano e vedrai (o, ancora meglio, convertili con carta e penna :Prrr: ).
Restituisce questi risultati sempre per il procedimento che ha scritto VICIUS?
Si. Se vuoi fare qualche prova puoi usare google per convertire velocemente dei numeri in binario e decimale. Basta cercare "8 in binary"
~FullSyst3m~
23-11-2008, 22:47
Ovviamente sì, confronta i risultati calcolatrice alla mano e vedrai (o, ancora meglio, convertili con carta e penna :Prrr: ).
:asd: non è che posso usare sempre carta e penna per ogni cosa però eh :D
Si. Se vuoi fare qualche prova puoi usare google per convertire velocemente dei numeri in binario e decimale. Basta cercare "8 in binary"
Si lo sapevo, grazie lo stesso ;) . Vai a riposarti VICIUS che il fumo che ti esce dalle orecchie si vede fino a qua :asd:
DanieleC88
23-11-2008, 23:16
:asd: non è che posso usare sempre carta e penna per ogni cosa però eh :D
E invece dovresti! È la cosa migliore quando cerchi di imparare da zero una cosa nuova. Io per il corso di algoritmi sto facendo tutti gli esercizi/ragionamenti/algoritmi con carta e penna; solo quando poi sono sicuro della correttezza di ciò che sto facendo, e ho capito il ragionamento che c'è dietro, scrivo (sempre su carta e penna :asd: ) del codice Python che risolva il problema, e alla fine lo vado a testare sul PC. ;)
~FullSyst3m~
24-11-2008, 03:48
E invece dovresti! È la cosa migliore quando cerchi di imparare da zero una cosa nuova. Io per il corso di algoritmi sto facendo tutti gli esercizi/ragionamenti/algoritmi con carta e penna; solo quando poi sono sicuro della correttezza di ciò che sto facendo, e ho capito il ragionamento che c'è dietro, scrivo (sempre su carta e penna :asd: ) del codice Python che risolva il problema, e alla fine lo vado a testare sul PC. ;)
Questo si, io non parlavo di imparare una cosa nuova. Per imparare una cosa nuova (come ora che sto facendo Python) faccio pure io quello che fai tu con carta e penna.
Comunque ti stai innamorando del pitone? :D
DanieleC88
24-11-2008, 10:27
Be', non è che mi stia "innamorando" di Python: è un linguaggio, e quindi uno strumento. Però concordo con cdimauro che lo definisce "pseudocodice eseguibile". :D
È molto comodo poter scrivere uno "pseudocodice" che puoi andare a testare direttamente sul tuo PC, se avessi dovuto farlo con del codice C ci avrei messo il triplo del tempo. Python, invece, essendo un linguaggio di più "alto" livello, mi dà la libertà di pensare al problema che sto risolvendo, prima di preoccuparmi dei dettagli implementativi.
Insomma, io conosco un po' di Python e per questo lo utilizzo per i miei scopi; sono sicuro che VICIUS potrebbe farti lo stesso mio discorso semplicemente sostituendo "Ruby" alle occorrenze di "Python". :p
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.