diff options
Diffstat (limited to 'Lib/random.py')
| -rw-r--r-- | Lib/random.py | 52 | 
1 files changed, 34 insertions, 18 deletions
| diff --git a/Lib/random.py b/Lib/random.py index 4efbb0a2b9..cd8583fe4a 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -8,6 +8,7 @@      ---------             pick random element             pick random sample +           pick weighted random sample             generate random permutation      distributions on the real line: @@ -43,12 +44,14 @@ from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin  from os import urandom as _urandom  from _collections_abc import Set as _Set, Sequence as _Sequence  from hashlib import sha512 as _sha512 +import itertools as _itertools +import bisect as _bisect  __all__ = ["Random","seed","random","uniform","randint","choice","sample",             "randrange","shuffle","normalvariate","lognormvariate",             "expovariate","vonmisesvariate","gammavariate","triangular",             "gauss","betavariate","paretovariate","weibullvariate", -           "getstate","setstate", "getrandbits", +           "getstate","setstate", "getrandbits", "choices",             "SystemRandom"]  NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0) @@ -105,15 +108,6 @@ class Random(_random.Random):          """ -        if a is None: -            try: -                # Seed with enough bytes to span the 19937 bit -                # state space for the Mersenne Twister -                a = int.from_bytes(_urandom(2500), 'big') -            except NotImplementedError: -                import time -                a = int(time.time() * 256) # use fractional seconds -          if version == 1 and isinstance(a, (str, bytes)):              x = ord(a[0]) << 7 if a else 0              for c in a: @@ -121,12 +115,11 @@ class Random(_random.Random):              x ^= len(a)              a = -2 if x == -1 else x -        if version == 2: -            if isinstance(a, (str, bytes, bytearray)): -                if isinstance(a, str): -                    a = a.encode() -                a += _sha512(a).digest() -                a = int.from_bytes(a, 'big') +        if version == 2 and isinstance(a, (str, bytes, bytearray)): +            if isinstance(a, str): +                a = a.encode() +            a += _sha512(a).digest() +            a = int.from_bytes(a, 'big')          super().seed(a)          self.gauss_next = None @@ -344,6 +337,28 @@ class Random(_random.Random):                  result[i] = population[j]          return result +    def choices(self, k, population, weights=None, *, cum_weights=None): +        """Return a k sized list of population elements chosen with replacement. + +        If the relative weights or cumulative weights are not specified, +        the selections are made with equal probability. + +        """ +        if cum_weights is None: +            if weights is None: +                choice = self.choice +                return [choice(population) for i in range(k)] +            else: +                cum_weights = list(_itertools.accumulate(weights)) +        elif weights is not None: +            raise TypeError('Cannot specify both weights and cumulative_weights') +        if len(cum_weights) != len(population): +            raise ValueError('The number of weights does not match the population') +        bisect = _bisect.bisect +        random = self.random +        total = cum_weights[-1] +        return [population[bisect(cum_weights, random() * total)] for i in range(k)] +  ## -------------------- real-valued distributions  -------------------  ## -------------------- uniform distribution ------------------- @@ -615,11 +630,11 @@ class Random(_random.Random):          # This version due to Janne Sinkkonen, and matches all the std          # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution"). -        y = self.gammavariate(alpha, 1.) +        y = self.gammavariate(alpha, 1.0)          if y == 0:              return 0.0          else: -            return y / (y + self.gammavariate(beta, 1.)) +            return y / (y + self.gammavariate(beta, 1.0))  ## -------------------- Pareto -------------------- @@ -734,6 +749,7 @@ choice = _inst.choice  randrange = _inst.randrange  sample = _inst.sample  shuffle = _inst.shuffle +choices = _inst.choices  normalvariate = _inst.normalvariate  lognormvariate = _inst.lognormvariate  expovariate = _inst.expovariate | 
