124 votes

Python mélangeant avec un paramètre pour obtenir le même résultat

import random
x = [1, 2, 3, 4, 5, 6]
random.shuffle(x)
print x

Je sais comment mélanger une liste, mais est-il possible de la mélanger avec un paramètre de telle sorte que le mélange produise le même résultat à chaque fois?

Quelque chose comme;

random.shuffle(x,parameter)

et le résultat est le même pour ce paramètre. Disons que le paramètre est 4 et que le résultat est [4, 2, 1, 6, 3, 5] à chaque fois.

242voto

abarnert Points 94246

Comme l'indique la documentation :

Les fonctions fournies par ce module sont en fait des méthodes liées à une instance cachée de la classe random.Random. Vous pouvez instancier vos propres instances de Random pour obtenir des générateurs qui ne partagent pas d'état.

Ainsi, vous pouvez simplement créer votre propre instance random.Random, avec sa propre graine, qui n'affectera en rien les fonctions globales :

>>> import random
>>> x = [1, 2, 3, 4, 5, 6]
>>> random.Random(4).shuffle(x)
>>> x
[4, 6, 5, 1, 3, 2]
>>> x = [1, 2, 3, 4, 5, 6]
>>> random.Random(4).shuffle(x)
>>> x
[4, 6, 5, 1, 3, 2]

(Vous pouvez également conserver l'instance Random et la réinitialiser avec une nouvelle graine au lieu d'en créer de nouvelles à chaque fois ; il n'y a pas beaucoup de différence.)

51voto

lejlot Points 45245

Vous pouvez définir la seed (qui accepte le paramètre) de votre générateur aléatoire, ce qui rendra votre méthode de mélange déterministe

import random
x = [1, 2, 3, 4, 5, 6]
random.seed(4)
random.shuffle(x)
print x

et le résultat devrait toujours être

[2, 3, 6, 4, 5, 1]

Pour "rerandomiser" le reste du code, vous pouvez simplement remettre votre générateur de nombres aléatoires à l'heure du système en exécutant

random.seed()

après la partie "déterministe" de votre code

11voto

Mark Points 1278

Mélanger avec une valeur fixe pour aléatoire NE fonctionne PAS bien! Exemple:

from random import shuffle
v = sum([[k] * 100 for k in range(10)], [])
print v[:40]
shuffle(v, random = lambda: 0.7)
print v[:40]

Donne la sortie:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 8, 0, 0, 9, 0, 0, 0, 9, 0, 0, 8, 0, 0, 7, 0, 0, 0, 9, 0, 0, 7, 0, 0, 8, 0, 0, 0, 7, 0, 0, 7, 0, 0, 8, 0, 0, 0, 9]

C'est similaire pour d'autres graines - pas très aléatoire (à première vue de toute façon... difficile à prouver). C'est parce que aléatoire n'est pas une graine - elle est réutilisée plusieurs fois. Démonstration:

def rand_tracker():
    rand_tracker.count += 1
    return random()
rand_tracker.count = 0
shuffle(v, random = rand_tracker)
print 'La fonction aléatoire a été appelée %d fois pour une liste de taille %d.' % (rand_tracker.count, len(v))

Qui montre:

La fonction aléatoire a été appelée 999 fois pour une liste de taille 1000.

Ce que vous devriez faire à la place, c'est la suggestion de @abarnert:

from random import Random
Random(4).shuffle(x)

Dans ce cas, une valeur fixe est parfaitement bonne.

TLDR : Utilisez la réponse de @abarnert, n'utilisez pas une fonction à valeur fixe pour aléatoire!

-1voto

Emmett J. Butler Points 1629

De la référence Python :

L'argument optionnel random est une fonction à 0 arguments retournant un float aléatoire dans [0.0, 1.0); par défaut, c'est la fonction random()

Vous pouvez utiliser une fonction lambda qui retourne toujours la même valeur comme seed pour shuffle:

In [7]: l = [1,2,3,4]
In [8]: random.shuffle(l, lambda: .5)

In [9]: l
Out[9]: [1, 4, 2, 3]

In [10]: l = [1,2,3,4]

In [11]: random.shuffle(l, lambda: .5)

In [12]: l
Out[12]: [1, 4, 2, 3]  # même ordre que Out[9]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X