Załóżmy, że mam następującą listę:
foo = ['a', 'b', 'c', 'd', 'e']
Jaki jest najprostszy sposób losowego pobrania elementu z tej listy?
Posługiwać się random.choice()
import random
foo = ['a', 'b', 'c', 'd', 'e']
print(random.choice(foo))
Do kryptograficznie bezpiecznych losowych wyborów (np. Do generowania hasła z listy słów) użyjsecrets.choice()
import secrets
foo = ['battery', 'correct', 'horse', 'staple']
print(secrets.choice(foo))
secrets
jest nowy w Pythonie 3.6, w starszych wersjach Pythona możesz użyć random.SystemRandom
klasy:
import random
secure_random = random.SystemRandom()
print(secure_random.choice(foo))
random.choice(foo)
zwrotu ma dwa różne wyniki?random.sample(lst, n)
Standard pseudo-random generators are not suitable for security/cryptographic purposes.
refJeśli chcesz losowo wybrać więcej niż jeden element z listy lub wybrać element z zestawu, zalecam użycie
random.sample
zamiast tego.Jeśli jednak wyciągasz tylko jeden element z listy, wybór jest mniej niezręczny, ponieważ użycie sample miałoby składnię
random.sample(some_list, 1)[0]
zamiastrandom.choice(some_list)
.Niestety wybór działa tylko dla pojedynczego wyjścia z sekwencji (takich jak listy lub krotki). Chociaż
random.choice(tuple(some_set))
może być opcją uzyskania pojedynczego przedmiotu z zestawu.EDYCJA: Używanie tajemnic
Jak wielu zauważyło, jeśli potrzebujesz bezpieczniejszych próbek pseudolosowych, powinieneś użyć modułu sekretów:
EDYCJA: Pythonic One-Liner
Jeśli potrzebujesz bardziej pythonowej linijki do wybierania wielu elementów, możesz użyć rozpakowywania.
źródło
secrets
Moduł BTW został dodany do standardowej biblioteki Python w wersji 3.6 python.org/dev/peps/pep-0506Jeśli potrzebujesz także indeksu, użyj
random.randrange
źródło
Począwszy od wersji Python 3.6 możesz używać
secrets
modułu, który jest lepszy odrandom
modułu do celów kryptografii lub bezpieczeństwa.Aby wydrukować losowy element z listy:
Aby wydrukować losowy indeks:
Aby uzyskać szczegółowe informacje, zobacz PEP 506 .
źródło
Proponuję skrypt do usuwania losowo wybranych pozycji z listy, dopóki nie będzie pusta:
Zachowaj a
set
i usuń losowo wybrany element (withchoice
), aż lista będzie pusta.Trzy przebiegi dają trzy różne odpowiedzi:
źródło
random.shuffle
list
W python 2:
W python 3:
źródło
random.choices
jest z wymianą, podczas gdyrandom.sample
jest bez wymiany.numpy
rozwiązanie:numpy.random.choice
W przypadku tego pytania działa ono tak samo, jak zaakceptowana odpowiedź (
import random; random.choice()
), ale dodałem je, ponieważ programista mógł już zaimportowaćnumpy
(jak ja), a także istnieją pewne różnice między dwiema metodami, które mogą dotyczyć rzeczywistego przypadku użycia.Aby zapewnić powtarzalność, możesz:
W przypadku próbek jednego lub więcej elementów , zwróconych jako
array
, przekażsize
argument:źródło
Jeśli chcesz mieć wartość zbliżoną do naprawdę losowej , sugeruję
secrets.choice
ze standardowej biblioteki (Nowość w Python 3.6.):Powyższe jest równoważne z moją poprzednią rekomendacją, używając
SystemRandom
obiektu zrandom
modułu zchoice
metodą - dostępną wcześniej w Pythonie 2:I teraz:
Jeśli chcesz deterministycznego wyboru pseudolosowego, użyj
choice
funkcji (która w rzeczywistości jest metodą powiązaną naRandom
obiekcie):Wydaje się losowy, ale w rzeczywistości tak nie jest, co możemy zobaczyć, jeśli wielokrotnie go resetujemy:
Komentarz:
Cóż, tak, możesz przekazać argument „seed”, ale zobaczysz, że
SystemRandom
obiekt po prostu go ignoruje :źródło
jeśli potrzebujesz indeksu, użyj:
random.choice robi to samo :)
źródło
random.choice(self, seq)
jestreturn seq[int(self.random() * len(seq))]
.randrange()
która oznacza, np.random.SystemRandom().randrange(3<<51)
wykazuje znaczne uprzedzenia. Westchnienie ...float
(podwójne IEEE) może przyjąć tylko skończoną liczbę wartości w [0,1).Random.random()
generuje wyjście w tradycyjny sposób: wybierz losową liczbę całkowitą[0, 2**53)
i podziel przez2**53
(53 to liczba bitów w podwójnej liczbie).random()
Zwraca więc 2 ** 53 podwajalne części, i możesz podzielić to równomiernie na N wyjść tylko wtedy, gdy N jest potęgą 2. Odchylenie jest małe dla małego N, ale zobaczcollections.Counter(random.SystemRandom().randrange(3<<51)%6 for i in range(100000)).most_common()
. (Java Random.nextInt () unika takich stronniczości.)2**40
(czyli 1099511627776) byłoby wystarczająco małe, aby stronniczość nie miała znaczenia w praktyce? Powinno to zostać wskazane w dokumentacji, ponieważ jeśli ktoś nie jest drobiazgowy, może nie spodziewać się problemów z tą częścią swojego kodu.random
używa,getrandbits
aby uzyskać odpowiednią liczbę bitów do wygenerowania wyniku dla większychrandrange
s (random.choice
również tego używa). Dotyczy to zarówno wersji 2.7, jak i 3.5. Używa się go tylkoself.random() * len(seq)
wtedy, gdygetrandbits
nie jest dostępne. To nie robi głupoty, jak myślisz.To jest kod ze zmienną, która definiuje losowy indeks:
To jest kod bez zmiennej:
Oto kod w najkrótszy i najmądrzejszy sposób:
(python 2.7)
źródło
Poniższy kod pokazuje, czy musisz wyprodukować te same produkty. Możesz także określić, ile próbek chcesz wyodrębnić. Metoda zwraca nową listę zawierającą elementy z populacji pozostawiając oryginalną populację niezmienione. Wynikowa lista jest uporządkowana w taki sposób, aby wszystkie podsegmenty również były prawidłowymi próbkami losowymi.
sample
źródło
Losowy wybór przedmiotu:
Aby zachować porządek na liście, możesz:
Duplikat https://stackoverflow.com/a/49682832/4383027
źródło
Możemy to również zrobić za pomocą randinta.
źródło
random.choice()
irandom.randrange()
?None
po prostu kopie puszkę do losowego, późniejszego punktu, w którym nieprawidłowy „element” wyzwala wyjątek; lub jeszcze gorzej, zamiast wyjątku otrzymujesz niepoprawny program i nawet o tym nie wiesz.Możesz po prostu:
źródło