Suponha que eu tenha a seguinte lista:
foo = ['a', 'b', 'c', 'd', 'e']
Qual é a maneira mais simples de recuperar um item aleatoriamente dessa lista?
Usar random.choice()
import random
foo = ['a', 'b', 'c', 'd', 'e']
print(random.choice(foo))
Para escolhas aleatórias seguras criptograficamente (por exemplo, para gerar uma frase secreta a partir de uma lista de palavras), usesecrets.choice()
import secrets
foo = ['battery', 'correct', 'horse', 'staple']
print(secrets.choice(foo))
secrets
é novo no Python 3.6, nas versões mais antigas do Python você pode usar a random.SystemRandom
classe:
import random
secure_random = random.SystemRandom()
print(secure_random.choice(foo))
random.choice(foo)
retorno consecutivas tem dois resultados diferentes?random.sample(lst, n)
Standard pseudo-random generators are not suitable for security/cryptographic purposes.
refSe você deseja selecionar aleatoriamente mais de um item de uma lista ou selecionar um item de um conjunto, recomendo o uso
random.sample
.Porém, se você estiver apenas puxando um único item de uma lista, a escolha será menos desajeitada, pois o uso de amostra teria a sintaxe em
random.sample(some_list, 1)[0]
vez derandom.choice(some_list)
.Infelizmente, porém, a escolha funciona apenas para uma única saída de seqüências (como listas ou tuplas). Embora
random.choice(tuple(some_set))
possa ser uma opção para obter um único item de um conjunto.EDIT: Usando segredos
Como muitos apontaram, se você precisar de amostras pseudo-aleatórias mais seguras, use o módulo secrets:
EDIT: Pythonic One-Liner
Se desejar uma linha única mais pitônica para selecionar vários itens, você pode usar a descompactação.
fonte
secrets
módulo BTW foi adicionado à biblioteca padrão do Python na versão 3.6 python.org/dev/peps/pep-0506Se você também precisar do índice, use
random.randrange
fonte
No Python 3.6, você pode usar o
secrets
módulo, que é preferível aorandom
módulo para criptografia ou segurança.Para imprimir um elemento aleatório de uma lista:
Para imprimir um índice aleatório:
Para detalhes, consulte PEP 506 .
fonte
Proponho um script para remover itens coletados aleatoriamente de uma lista até que ela fique vazia:
Mantenha um
set
e remova o elemento selecionado aleatoriamente (comchoice
) até que a lista esteja vazia.Três execuções fornecem três respostas diferentes:
fonte
random.shuffle
alist
uma vez e quer iterate-lo ou colocá-la para produzir resultados. Ou resultaria em um fluxo "selecionar aleatoriamente sem repetições" perfeitamente adequado, mas a aleatoriedade seria introduzida no início.No python 2:
No python 3:
fonte
random.choices
está com substituição enquantorandom.sample
está sem substituição.numpy
solução:numpy.random.choice
Para esta pergunta, funciona da mesma forma que a resposta aceita (
import random; random.choice()
), mas eu a adicionei porque o programador já pode ter importadonumpy
(como eu) e também existem algumas diferenças entre os dois métodos que podem estar relacionados ao seu caso de uso real.Para reprodutibilidade, você pode fazer:
Para amostras de um ou mais itens , retornados como um
array
, passe osize
argumento:fonte
Se você quiser quase aleatoriamente , sugiro
secrets.choice
da biblioteca padrão (Novo no Python 3.6.):O acima é equivalente à minha recomendação anterior, usando um
SystemRandom
objeto dorandom
módulo com ochoice
método - disponível anteriormente no Python 2:E agora:
Se você deseja uma seleção pseudo-aleatória determinística, use a
choice
função (que na verdade é um método vinculado a umRandom
objeto):Parece aleatório, mas na verdade não é, o que podemos ver se o repetirmos novamente:
Um comentário:
Bem, sim, você pode passar um argumento "semente", mas verá que o
SystemRandom
objeto simplesmente o ignora :fonte
se você precisar do índice, use:
random.choice faz o mesmo :)
fonte
random.choice(self, seq)
isreturn seq[int(self.random() * len(seq))]
.randrange()
qual significa, por exemplo,random.SystemRandom().randrange(3<<51)
exibe viés significativo. Suspiro ...float
(um duplo IEEE) só pode receber um número finito de valores em [0,1).Random.random()
gera sua saída da maneira tradicional: escolha um número inteiro aleatório[0, 2**53)
e divida por2**53
(53 é o número de bits em um dobro). Portanto,random()
retorna 2 ** 53 duplos equiprobáveis, e você pode dividir isso uniformemente em saídas N apenas se N for uma potência de 2. O viés é pequeno para N pequeno, mas vejacollections.Counter(random.SystemRandom().randrange(3<<51)%6 for i in range(100000)).most_common()
. (O Random.nextInt () de Java evita esse viés.)2**40
(1099511627776) seria pequeno o suficiente para que o viés não importasse na prática? Isso realmente deve ser apontado na documentação, porque se alguém não for meticuloso, talvez não espere que surjam problemas dessa parte do código.random
usagetrandbits
para obter um número adequado de bits para gerar um resultado pararandrange
s maiores (random.choice
também está usando isso). Isso é verdade tanto no 2.7 quanto no 3.5. Ele usa apenasself.random() * len(seq)
quandogetrandbits
não está disponível. Não está fazendo a coisa estúpida que você pensa que é.Este é o código com uma variável que define o índice aleatório:
Este é o código sem a variável:
E este é o código da maneira mais rápida e inteligente possível:
(python 2.7)
fonte
O código a seguir demonstra se você precisa produzir os mesmos itens. Você também pode especificar quantas amostras deseja extrair.
O
sample
método retorna uma nova lista contendo elementos da população, mantendo inalterada a população original. A lista resultante está na ordem de seleção, para que todas as sub-fatias também sejam amostras aleatórias válidas.fonte
Seleção aleatória de itens:
Para preservar a ordem da lista, você pode:
Duplicado de https://stackoverflow.com/a/49682832/4383027
fonte
Também podemos fazer isso usando randint.
fonte
random.choice()
erandom.randrange()
?None
apenas chuta a lata para algum ponto posterior aleatório, onde o "elemento" inválido dispara uma exceção; ou pior ainda, você obtém um programa incorreto em vez de uma exceção e nem o conhece.Você poderia apenas:
fonte