1# random.choice2def choice(self, seq):
3"""Choose a random element from a non-empty sequence."""4try:
5 i = self._randbelow(len(seq))
6except ValueError:
7raise IndexError('Cannot choose from an empty sequence') from None
8return seq[i] 1# random.choices 2def choices(self, population, weights=None, *, cum_weights=None, k=1):
3"""Return a k sized list of population elements chosen with replacement.
4 5 If the relative weights or cumulative weights are not specified,
6 the selections are made with equal probability.
7 8""" 9 random = self.random
10if cum_weights is None:
11if weights is None:
12 _int = int
13 total = len(population)
14return [population[_int(random() * total)] for i in range(k)]
15 cum_weights = list(_itertools.accumulate(weights))
16elif weights isnot None:
17raise TypeError('Cannot specify both weights and cumulative weights')
18if len(cum_weights) != len(population):
19raise ValueError('The number of weights does not match the population')
20 bisect = _bisect.bisect
21 total = cum_weights[-1]
22 hi = len(cum_weights) - 1
23return [population[bisect(cum_weights, random() * total, 0, hi)]
24for i in range(k)] 1# random.sample 2 3def sample(self, population, k):
4"""Chooses k unique random elements from a population sequence or set.
5 6 Returns a new list containing elements from the population while
7 leaving the original population unchanged. The resulting list is
8 in selection order so that all sub-slices will also be valid random
9 samples. This allows raffle winners (the sample) to be partitioned
10 into grand prize and second place winners (the subslices).
1112 Members of the population need not be hashable or unique. If the
13 population contains repeats, then each occurrence is a possible
14 selection in the sample.
1516 To choose a sample in a range of integers, use range as an argument.
17 This is especially fast and space efficient for sampling from a
18 large population: sample(range(10000000), 60)
19"""2021# Sampling without replacement entails tracking either potential22# selections (the pool) in a list or previous selections in a set.2324# When the number of selections is small compared to the25# population, then tracking selections is efficient, requiring26# only a small set and an occasional reselection. For27# a larger number of selections, the pool tracking method is28# preferred since the list takes less space than the29# set and it doesn't suffer from frequent reselections.3031if isinstance(population, _Set):
32 population = tuple(population)
33ifnot isinstance(population, _Sequence):
34raise TypeError("Population must be a sequence or set. For dicts, use list(d).")
35 randbelow = self._randbelow
36 n = len(population)
37ifnot 0 <= k <= n:
38raise ValueError("Sample larger than population or is negative")
39 result = [None] * k
40 setsize = 21 # size of a small set minus size of an empty list41if k > 5:
42 setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets43if n <= setsize:
44# An n-length list is smaller than a k-length set45 pool = list(population)
46for i in range(k): # invariant: non-selected at [0,n-i)47 j = randbelow(n-i)
48 result[i] = pool[j]
49 pool[j] = pool[n-i-1] # move non-selected item into vacancy50else:
51 selected = set()
52 selected_add = selected.add
53for i in range(k):
54 j = randbelow(n)
55while j in selected:
56 j = randbelow(n)
57 selected_add(j)
58 result[i] = population[j]
59return result