Ogni buon programmatore, prima o poi, dovrà generare un numero casuale; si tratta di un tema che interessa non solo chi programma videogiochi ma anche chi deve, per esempio, generare un identificativo o una password.

In questo articolo vediamo cosa ci offre Python al riguardo!

cube530 260

Chi come me proviene da linguaggi di più basso livello, per la generazione di un numero casuale si aspetta due funzioni: una per inizializzare il generatore di numeri casuali e un'altra per ottenere un valore casuale.

In linguaggio C abbiamo queste due funzioni:

void srand (unsigned int seed);
int rand (void);

La funzione rand() ritorna un intero compreso fra 0 e RAND_MAX: per ottenere dei valori in intervalli diversi basta un pò di matematica...

Di base in Python ritroviamo queste due funzioni:

random.seed()
random.random()

In questo caso la funzione random.random() restituisce un valore a virgola mobile x tale che 0 <= x < 1.
Volendo "tradurre" la funzione rand() del linguaggio C ci possiamo affidare al metodo randrange(start,stop) che genera un valore intero x tale che start <= x < stop.

Tutto qui? Certo che no! Provate solo a dare un'occhiata alla documentazione ufficiale https://docs.python.org/3/library/random.html.

Uno dei primi programmi che scrissi in Python mi serviva per generare una sequenza di colonne da giocare al superenalotto; i 90 possibili numeri li posizionavo tutti all'interno di 15 colonne da 6 numeri.
In questo modo ero sicuro che avrei azzeccato tutti i 6 numeri estratti e forse, con un po' di fortuna, questi si sarebbero trovati nella stessa colonna.
Morale: non ho mai vinto niente!

Questo è il codice:

import random

print("colonne superenalotto")
estratti = []
for i in range(15):
    colonna = []    
    for j in range(6):
        while True:                         
            val = random.randrange(1,91)    # estrae un numero
            if not (val in estratti):       # continuiamo solo se non era già estratto
                break
        colonna.append( val )
        estratti.append( val )
    colonna.sort()
    print (colonna)

e questo è un esempio di output:

colonne superenalotto
[13, 28, 53, 54, 79, 84]
[8, 38, 48, 49, 58, 73]
[1, 32, 36, 37, 70, 90]
[11, 18, 34, 46, 59, 68]
[4, 23, 66, 75, 76, 78]
[35, 39, 50, 51, 57, 71]
[12, 43, 45, 52, 55, 67]
[3, 14, 31, 62, 80, 89]
[5, 19, 60, 69, 85, 86]
[10, 16, 20, 22, 24, 61]
[7, 27, 41, 44, 81, 88]
[2, 26, 33, 63, 74, 83]
[6, 15, 25, 42, 56, 77]
[9, 21, 64, 65, 72, 87]
[17, 29, 30, 40, 47, 82]

Il codice, molto banalmente, estraeva numeri da 1 a 90, tenendosi traccia dei numeri già estratti per non riproporli e organizzava l'estrazione in 15 liste da 6 numeri.

Ma davvero c'è bisogno di scrivere tutto questo codice in Python?

Naturalmente no: a quel tempo non conoscevo il metodo shuffle() che "mescola" gli elementi.
Nel programmino riscritto qui sotto, dopo aver generato la lista dei numeri da 1 a 90, richiamo shuffle() per mescolarli e poi con due cicli provvedo a stampare le 15 colonne da 6 numeri.

import random

print("colonne superenalotto")
numeri = list(range(1,91))
random.shuffle(numeri)                
i=0
for col in range(15):
    colonna=list(numeri[i:i+6])
    colonna.sort()
    i=i+6
    print (colonna)

Molto meglio direi. La lista temporanea per la colonna l'ho mantenuta, in modo da permettere l'ordimento dei numeri di ciascuna colonna e semplificare la compilazione della schedina!

Tutto qui? No, come già detto in precedenza il modulo random offre diversi altri metodi molto utili.

Prendiamo ad esempio choice(seq) che restituisce un valore a caso fra quelli presenti nella sequenza seq.

import random
print(random.choice("abcdef"))

Se provate questo programma otterrete la stampa di un carattere a caso fra "a" ed "f"; mi raccomando, però, non fate come me che il mio file di prova l'ho chiamato "random.py"... la import non potrà importerare il vero modulo "random"!!!

Il metodo choice() può essere molto utile per generare delle password in maniera automatica: ad esempio, il codice qui sotto genera una stringa di 5 caratteri:

import random
import string

# generatore di password
pwd = ""
for i in range(5):
    pwd = pwd + random.choice(string.ascii_uppercase + string.digits)
print(pwd)

Sì può generare il tutto anche in una sola riga, con le list comprehension:

import random
import string

# generatore di password
pwd=([random.choice(string.ascii_uppercase + string.digits) for _ in range(5)])
print(pwd)

però il risultato non è una stringa...

['V', 'D', '1', 'E', 'Y']

Per aver una stringa, dalla lista, si può utilizzare il metodo join, ovvero l'alternativa alla concatenazione con +:

import random
import string
# generatore di password
pwd=(''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(5)))
print(pwd)

ed ecco una password di esempio: IWHJ8.

Il modulo random di Python offre innumerevoli altre possibilità: consiglio vivamente di leggere la documentazione!

Se poi volete approfondire la tematica, sia dal punto di vista teorico che da quello pratico, vi consiglio un bel giro in https://www.random.org/: non solo vi troverete delle applicazioni molto interessanti (come il "Random Geographic Coordinates") ma anche parecchia documentazione.

Buon divertimento!!!

FONTI
https://docs.python.org/3/library/random.html
https://www.random.org/