Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Récupérer résultat de random() condition d'une boucle while

+3 votes

j'ai ce code: (Le code en dessous n'a certainement pas de sens car j'ai essayé de le simplifier au maximum).

from random import randint

liste = [i for i in range(100)]

while randint(0, 110) in liste:
    continue

Je voudrais savoir comment faire pour récupérer le résultat de randint(0, 110) lorsque la boucle est terminé pour faire un:

liste.append(resultat_de_randint)
demandé 12-Mai-2016 par daimebag (196 points)
edité 14-Mai-2016 par max

4 Réponses

+5 votes
 
Meilleure réponse

Je ferais ça avec une boucle for et un break plutôt, pour avoir accès à la valeur. En contrepartie, il faut faire un générateur qui produit la valeur aléatoire.

Par exemple:

from random import randint

liste = list(range(100))

def genrandint(a, b):
    while True:
        yield randint(a, b)

for value in genrandint(0, 110):
    # faire des trucs ici
    if value in liste:
        break
    # ou bien faire des trucs là

# value contient la dernière valeur qui a fait sortir de la boucle
répondu 13-Mai-2016 par bubulle (2,248 points)
sélectionné 13-Mai-2016 par daimebag

+1 pour le gain de lisibilité du au découplage. (et parce qu'un générateur, c'est toujours rigolo)

–1 vote

un truc du genre

from random import randint

liste = [i for i in range(100)]

while randint(0, 110) in liste:
    continue
else:
    liste.append(resultat_de_randint)

le else intervient que le while vaut false

répondu 12-Mai-2016 par foxmask (2,888 points)

mais d'où vient 'resultat_de_randint' ?
en l'état, le code ne marche pas, non ?

Il vient de son code qu'il ne nous a pas montré

Nan tu vise juste Bubulle. Justement c'était ça m'a question^^. Est-ce qu'un truc en python permet de récupérer le résultat de la dernière commande exécuté. (Et comme je n'ai pas nommé l'exécution de mon randquelquechose)

Comme le "_" dans un shell python quoi.

Ça me paraissait peu probable mais je voulais poser la question pour assouvir ma curiosité. Des fois que...

Edit: Bon j'y avais pas pensé mais j'ai testé mon code dans un shell et ai essayé de récupérer le résultat avec "_", donc je crois que j'ai la réponse à ma question. Désolé de vous avoir dérangé avec ça. Mais merci quand même car j'ai appris des trucs ici!

+2 votes

Avec ce code là, je ne vois pas comment c'est possible.

Mais avec une petite modification:

from random import randint

liste = [i for i in range(100)]

random_int = liste[0] if liste else None
while random_int in liste:
    random_int = randint(0, 110)

liste.append(random_int)

La troisième ligne s'assure que la condition est vraie à la première itération si la liste est non vide.

Une autre manière de faire, pas très DRY mais toujours valide, serait celle-ci:

random_int = randint(0, 110)

Note décorrélée du problème

Pour avoir une liste à partir du range, plutôt que:

liste = [i for i in range(100)]

Il suffit de:

liste = list(range(100))

De plus, vu l'usage de la variable liste, il serait plus sage dans ce cas de l'initialiser ainsi:

liste = range(100)

Avec le code actuel, cela mènera à un gain de temps et de mémoire.


Autre note, passablement corrélée au problème

L'algo implémenté par la boucle, ayant pour objectif d'ajouter un nombre non présent dans une liste, est coûteux, et pourrait potentiellement ne jamais se finir. (avec une malchance d’anthologie, ou un générateur de nombre pseudo aléatoire pas très bien calibré)
En vrai, sauf nécessité de perfs monstrueuse, il n'y a pas vraiment de problème si ce code n'est pas critique et reste un jouet.

Une autre manière de faire serait d'isoler les valeurs possible (de 0 à 110) et les valeurs connues (celle stockées dans liste),
et de ne choisir que parmi la différence des deux.
Il s'agit d'un sacrifice de la mémoire sur l'autel du temps de calcul.

import random

liste = set(range(100))
valeurs_possibles = set(range(111))

# Ajouter dans la liste un élément possible choisi
#  au hasard parmis les valeurs possibles
#  mais non présentes dans la liste.
random_int = random.choice(valeurs_possibles - liste)
liste.add(random_int)
répondu 12-Mai-2016 par lucas (2,332 points)
edité 12-Mai-2016 par lucas

Pas con le montage avec "random_choice".

En réalité c'est pas une liste mais plutôt un dico qui contiendrai des instances de la même classe au nom généré aléatoirement(qui elles-mêmes appelleraient d'autre classes, 'fin m'voyez quoi).
Chaque instance supprimerait son index du dico une fois qu'elle aurait exécuté son boulot avec un "del dico[instance_bidule)" pour libérer la place.

Le but de ma question en fait était surtout de savoir si techniquement il était possible de faire de cette manière:

while randint(x, y) in dico: #Ou random
    continue

exec("dico[{0}] = Instance({1}, {2}, {3})".format(formule_magique, param1, param2, param3))

Merci en tout cas pour vos réponses, j'apprends des trucs au passage!

Oui, c'est possible, exactement comme je l'ai indiqué ; il faut modifier un peu le code.

value = randint(x, y)
while value in dico: #Ou random
    value = randint(x, y)

exec("dico[{0}] = Instance({1}, {2}, {3})".format(value, param1, param2, param3))

Note également que ma remarque sur l'utilisation de random.choice est toujours valide, même si l'itérable est un dictionnaire… Il suffit de créer un set depuis les clefs.


Pense à accepter la réponse qui t'as permis de résoudre ton problème.

0 votes

Tout le monde a utilisé des compréhensions de listes, mais sans passer le randint() dedans.

Un simple

liste = [randint(0, 110) for n in range(100)]

Convient très bien.

répondu 13-Mai-2016 par Hier j'ai mangé un chat
...