Si può fare ma c’è qualche aspetto da considerare.
Intanto le abitudini di una volta, complice una possibilità del Fortran non presente in Python. Nel Fortran (parlo delle versioni vecchie 77 e precedenti; il 77 è tuttora usato per quel che ne so) ci sono due tipi di sottoprogrammi: le funzioni e le subroutines. Queste ultime, affini alle funzioni C di tipo void
erano di gran lunga le preferite. C’è una giustificazione: le variabili sono passate per indirizzo (reference, non so se i due termini sono rigorosamente equivalenti, questi erano quelli correnti). Esempio:
N = 8
CALL DOPPIO (N)
PRINT* N
SUBROUTINE DOPPIO (N)
N = 2 * N
END
Il risultato che ottengo è 16
, cioè il valore di N
modificato nella subroutine viene conservato nel main, è cambiato il valore memorizzato all’indirizzo della variabile e questo è quello che ho passato al sottoprogramma. Con Python (per quel che ne so) questo non è possibile, ecco qua:
$ py3
>>> def doppio (n):
... n = 2 * n
... print('in doppio:', n)
...
>>> n = 8
>>> doppio (n)
in doppio: 16
>>> print (n)
8
alla funzione doppio
ho passato il valore 8
e al di fuori di questa il valore di n
resta 8
indipendentemente da quanto avvenuto nel sottoprogramma. Ovvia la soluzione, la stesa da sempre, in Fortran:
N = 8
N = IDOPPIO (N)
PRINT* N
FUNTION IDOPPIO (N)
N = 2 * N
RETURN (N)
END
Notare che ho cambiato il nome alla funzione, variabili e funzioni sono di default REAL*4
tranne quelle il cui nome inizia con le lettere dell’intervallo [I
..N
] che sono INTEGER*2
o INTEGER*4
a seconda della versione e delle opzioni di compilazione. Caratteristico del Fortran è che la precisione viene espressa in byte e non in bit.
In Python la funzione può ritornare una lista, torna comoda per le subroutines:
$ py3
>>> def pot(a, b, p):
... a = a ** p
... b = b ** p
... return a, b
...
>>> r = pot(3, 4, 2)
>>> print(r)
(9, 16)
>>> # ovviamente
... a, b = pot(3, 4, 2)
>>> print(a)
9
>>> print(b)
16
Quindi una prima regola pratica: scrivere funzioni che ritornano i valori delle variabili che ci servono. Ma ci sono dei casi in cui questa pratica non basta, il caso di arrays e matrici di dimensioni rilevanti.
In Fortran c’è l’istruzione COMMON
:
COMMON /DATI/ A, B(10), C, D
COMMON /MAT/ P(20, 20), R(10, 10, 10)
Ogni funzione o subroutine che usi A
, B
, C
o D
dovrà dichiarare il COMMON /DATI/
, idem per il caso di /MAT/
.
In Python si ottiene un risultato simile (meno granulare, meno raffinato ma forse meno soggetto a bug) con le variabili globali:
$ py3
>>> #a = 0
>>> b = []
>>>
>>> def popola_dati():
... global a
... a = 42
... for c in range(10):
... b.append(c ** 2)
...
>>>
>>> popola_dati()
>>> print('a =', a)
a = 42
>>> print('b =', b)
b = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
OK, notare che a
devo dichiararla global
nella funzione a differenza di b
che dev’essere inizializzato nel main e diventa automaticamente globale. b
è una lista, non esattamente l’equivalente degli arrays e matrici del Fortran. Le liste sono versatili ma onerose, da modificare, in un post successivo, pausa 😎
⭕
Trackback
[…] Continuo da qui. […]