]> granicus.if.org Git - python/commitdiff
SF bug #801342: Bug (documentation or real, your choice) in random.sample.
authorRaymond Hettinger <python@rcn.com>
Sat, 6 Sep 2003 04:25:54 +0000 (04:25 +0000)
committerRaymond Hettinger <python@rcn.com>
Sat, 6 Sep 2003 04:25:54 +0000 (04:25 +0000)
random.sample() uses one of two algorithms depending on the ratio of the
sample size to the population size.  One of the algorithms accepted any
iterable population argument so long as it defined __len__().  The other
had a stronger requirement that the population argument be indexable.

While it met the documentation specifications which insisted that the
population argument be a sequence, it made random.sample() less usable
with sets.  So, the second algorithm was modified to coerce non-indexable
iterables and dictionaries into a tuple before proceeding.

Lib/random.py
Lib/test/test_random.py

index 7210f62b1008ea2429f9ebfc1525e1d03cddcca8..2530c39ac76b633b0e1c594f71297eb1d52827cc 100644 (file)
@@ -258,6 +258,10 @@ class Random(_random.Random):
                 result[i] = pool[j]
                 pool[j] = pool[n-i-1]   # move non-selected item into vacancy
         else:
+            try:
+                n > 0 and (population[0], population[n//2], population[n-1])
+            except (TypeError, KeyError):   # handle sets and dictionaries
+                population = tuple(population)
             selected = {}
             for i in xrange(k):
                 j = _int(random() * n)
index c9103e8f87b77f424c6787ef467f0da0c095de5a..fbd418457a68ba185f0c53aa74a6518b79d37482 100644 (file)
@@ -86,6 +86,16 @@ class TestBasicOps(unittest.TestCase):
             else:
                 self.fail()
 
+    def test_sample_inputs(self):
+        # SF bug #801342 -- population can be any iterable defining __len__()
+        from sets import Set
+        self.gen.sample(Set(range(20)), 2)
+        self.gen.sample(range(20), 2)
+        self.gen.sample(xrange(20), 2)
+        self.gen.sample(dict.fromkeys('abcdefghijklmnopqrst'), 2)
+        self.gen.sample(str('abcdefghijklmnopqrst'), 2)
+        self.gen.sample(tuple('abcdefghijklmnopqrst'), 2)
+
     def test_gauss(self):
         # Ensure that the seed() method initializes all the hidden state.  In
         # particular, through 2.2.1 it failed to reset a piece of state used