PDA

Visualizza la versione completa : [Python] Risultato funzione


Pacio88
09-07-2008, 23:30
Premetto che esercitandomi mi sono detto di provare a scrivere un programmino che calcoli quante vocali compaiano in una parola. Questo è quello che ho elaborato:


def ContaVocali(x):
voc=0
i=0
lung=len(x)
while i<lung:
Let=x[i]
if Let=='a' or Let=='e' or Let=='i' or Let=='o' or Let=='u' or Let=='A' or Let=='E' or Let=='I' or Let=='O' or Let=='U':
voc=voc+1
i=i+1
else:
i=i+1
return voc

x=raw_input("Inserisci un nome: ")
v=ContaVocali(x)
print "Numero delle vocali:", v

Osservando il codice ho pensato di fare questa aggiunta per calcolare anche le consonanti:



def ContaVocali(x):
voc=0
i=0
lung=len(x)
while i<lung:
Let=x[i]
if Let=='a' or Let=='e' or Let=='i' or Let=='o' or Let=='u' or Let=='A' or Let=='E' or Let=='I' or Let=='O' or Let=='U':
voc=voc+1
i=i+1
else:
i=i+1
return voc

x=raw_input("Inserisci un nome: ")
v=ContaVocali(x)
c=len(x)-ContaVocali(x)
print "VOCALI:", v
print "CONSONANTI:", c
y=raw_input("Premi un tasto per uscire")

Tuttavia ho notato che sarebbe stato suficcente all'interno della funzione ContaVocali dopo l'struzione else: aggiungere una variabile che come nelle poche righe sopra mi contasse le consonanti. Il mio problema era come poter utlizzare due risultati forniti dalla medesima funzione, ovvero se nel caso originale la funzione ritorna un valore che indica le vocali adesso vorrei che esprimesse due risultati.

Spero di essermi spiegato.

P.S. Sto studiando concretamente il Python da una settimana se ci sono correzioni al codice per renderlo più "elegante" sono ben accette.

Ringrazio anticipatamente tutti coloro che mi risponderanno.

GreyFox86
10-07-2008, 10:35
Per migliorare il codice puoi usare il costrutto Variabile in Lista


>>> Let="E".lower()
>>> Let in ['a','e','i','o','u']
True

Per far restiture entrambi i risultati usa una n-upla:


function bla(...):
...
return (val1, val2)

Var1, Var2 = bla(..)

billiejoex
10-07-2008, 14:18
Ci saranno sicuramente metodi migliori ma questo potrebbe essere un approccio un po' più performante.
Puoi usare set() per ottenere le singole lettere contenute nella parola cosicchè successivamente iteri [u]soltanto su quelle[u] utilizzando ''.count() per contare le occorrenze.
Questo dovrebbe essere tanto più efficiente quanto è più lungo il testo dato in pasto alla funzione.





# -*- coding: latin1 -*-

consonanti = 'bcdfghjklmnpqrstvwxyz'
vocali = 'aeiouàèìòù'

def conta(parola):
cons = 0
vocs = 0
parola = parola.lower()
lettere = set(parola)
for lettera in lettere:
if lettera in consonanti:
cons += parola.count(lettera)
elif lettera in vocali:
vocs += parola.count(lettera)
else:
# carattere estraneo (!$%& ecc...)
pass
print "vocali=%s, consonanti=%s" %(vocs, cons)

GreyFox86
10-07-2008, 14:34
Premesso che non conoscendo a fondo python non posso dirlo con certezza, ma di primo impatto mi sembrerebbe un po' più macchinoso con la gestione del set... è vero che il loop viene notevolmente ridotto, ma la trasformazione in set e poi ancora i loop impliciti di count() per contare le occorrenze non dovrebbero aumentare la complessità generale?
Forse è più veloce perchè anche se fanno più giri, sono builtin?

billiejoex
10-07-2008, 15:15
Dipende dalla lunghezza della stringa data in input.
Effettivamente se parliamo di parole, ovvero stringhe che difficilmente sono superiori a 10 caratteri di lunghezza, è più veloce iterare su ogni singolo elemento.
Se però si volessere contare le occorrenze di ogni singola lettera su di una stringa molto lunga (es: un testo) risulta più performante utilizzare set() e ''.count().
Un po' di benchmark:



# -*- coding: latin1 -*-

consonanti = 'bcdfghjklmnpqrstvwxyz'
vocali = 'aeiouàèìòù'

def conta1(parola):
cons = 0
vocs = 0
parola = parola.lower()
lettere = set(parola)
for lettera in lettere:
if lettera in consonanti:
cons += parola.count(lettera)
elif lettera in vocali:
vocs += parola.count(lettera)
else:
# carattere estraneo (!$%& ecc...)
pass
return cons, vocs

def conta2(parola):
cons = 0
vocs = 0
for x in parola:
if x in consonanti:
cons +=1
elif x in vocali:
vocs += 1
return cons, vocs

import timeit
print timeit.Timer('conta1("difficile")', 'from __main__ import conta1').timeit(1000)
print timeit.Timer('conta2("difficile")', 'from __main__ import conta2').timeit(1000)
print timeit.Timer('conta1("difficile" * 1000)', 'from __main__ import conta1').timeit(1000)
print timeit.Timer('conta2("difficile" * 1000)', 'from __main__ import conta2').timeit(1000)


A me ritorna:

0.0187870246079 secondi utilizzando set() su stringa corta
0.00785407083861 secondi utilizzando for su stringa corta
1.42217516472 secondi utilizzando set() su stringa lunga
5.30397271162 secondi utilizzando for su stringa lunga

Cmq sicuramente esisteranno approcci migliori, sia che utilizzare set() che iterare su tutta la stringa.

GreyFox86
10-07-2008, 15:20
La differenza su stinghe lunghe è notevole alla fine... sembra più conveniente basarsi sulle builtin il più possibile quindi.
Grazie per il chiarimento ^^

billiejoex
10-07-2008, 15:23
La differenza su stinghe lunghe è notevole alla fine... sembra più conveniente basarsi sulle builtin il più possibile quindi.
Essendo scritti in C e ottimizzati al massimo quasi sempre è così.
Inoltre i cicli for in Python non sono velocissimi.

billiejoex
10-07-2008, 15:30
Questo sembra essere più veloce dei due sopra:



def conta3(parola):
parola = parola.lower()
cons = 0
vocs = 0
for x in consonanti:
cons += parola.count(x)
for x in vocali:
vocs += parola.count(x)
return cons, vocs


0.039284881179 secondi con la stringa corta e 1.15162010814 con la stringa lunga (5x più veloce dell'approccio con set() e 10x dell'approccio col for).

billiejoex
10-07-2008, 15:33
Ancora più veloce (poi la smetto :))



def conta3(parola):
parola = parola.lower()
cons = 0
vocs = 0
for x in consonanti:
if x in parola:
cons += parola.count(x)
for x in vocali:
if x in parola:
vocs += parola.count(x)
return cons, vocs


Risultati:

0.0201964216122
0.777120555825

GreyFox86
10-07-2008, 15:48
niente male questo

Loading