sabato 17 novembre 2012

Mission Python: Le funzioni. Parte quarta

Ebbene sì, ancora roba sulle funzioni. Ma diverso, cominciamo con un quiz.
John Baez (uno pheego assay) ci chiede di calcolare il valore dell'espressione in figura, tenendo presente che


 x^x^x^x significa x^(x^(x^x)),

come dice qui.

Facile vero? Anzi immediata, intanto si può stimare al volo a quanto converge, ma se leggete il post trovate cose che solo i mate..., prendi Shanthanu Bhardwaj, e quindi "the more math we know the less tiring work we need to do!  :-)" --OK sto divagando, torniamo a noi.

Non ci sarebbe nemmeno bisogno di introdurre una funzione ma facciamo le cose come dico io, che devo introdurre altre cose, ecco pt2f.py:

#!/usr/bin/python
# -*- coding: utf-8 -*-

#pt2f - vedi https://plus.google.com/117663015413546257905/posts/UyaMfvF18kw

v2 = 2.0 ** 0.5 # costante globale

def calcrad(res):
 global num_iter
 print num_iter, res
 if num_iter == 9:
  return
 else:
  num_iter += 1
  v = v2 ** res
  res = calcrad(v)

#main
num_iter = 1 # variabile globale 
             # contiene il numero dell'iterazione
calcrad(v2)
print

La funzione chiama se stessa, è ricorsiva, ma questo l'abbiamo già visto, non è una novità. Non dovrebbe stupire più di tanto che nel main il valore ritornato dalla funzione non viene "estratto", cosa che con altri linguaggi vecchio stile darebbe errore, ma dal C in poi anche questo è normale (quasi).

Allora cos'è la cosa particolare? Le variabili globali. Ce ne sono due: la costante v2 (l'ho chiamata v2 perché è quasi uguale a come scriviamo radice di 2); che sia una costante non è scritto da nessuna parte, lo sappiamo solo noi. L'altra variabile globale è num_iter (che sta per numero dell'iterazione, c'è anche il commento).

E adesso il quiz: perché all'interno della funzione ho dovuto scrivere l'istruzione globale num_iter, cosa che non ho fatto per v2 che pure viene usata nella funzione?
Qualcuno sa la risposta? qualcuno che non conosce C/C++, Pascal/Delphi e simili?
OK, Bit3Lux e io siamo buoni, ve lo diciamo dai, anzi ecco un esempio molto più semplice (sol.py):

#!/usr/bin/python
# -*- coding: utf-8 -*-

def func(t):
 t *= 2
 print 'dentro', t
 return t

#main
t = 5
for c in range(5):
 print 'main ', t
 q = func(t)


Chiaro? Alla funzione passiamo il valore 5, questo viene raddoppiato (e funziona, lo scrive) ma al ritorno nel main vale di nuovo 5.
Chiaro?
Ah sì alla funzione viene passato il valore della variabile, non il suo indirizzo; quindi quando si esce dalla funzione il valore è quello dell'indirizzo. Proprio come il C/C++.
OK? beh...
Ma capita sempre così? proviamo con una lista (lst.py):

#!/usr/bin/python
# -*- coding: utf-8 -*-

def duplica(lst):
 for c in range(len(lst)):
  lst[c] *= 2

lst = [1, 2, 3]
print lst
duplica(lst)
print lst

OPS! la lista viene passata per indirizzo, direbbe qualcuno che non conosce il C/C++.
OPS! proprio come gli array in C/C++, direbbe qualcuno che conosce il C/C++.

Sì, Python non finisce di sorprenderci, sapeste cosa ci attende prossimamente...

Il caro Juhan.

Vi ricordo che l'indice di "Mission Python" lo potete trovare qui.

Alla prossima!

1 commento: