Python标准库random.sample函数中常量的合理性探究
random.sample Exist Great question! I’ve dug into the random.sample source code a bunch myself, so let’s break down the reasoning behind those constants—they’re rooted in probability math and real-world performance tradeoffs, not arbitrary picks.
First, let’s recap the two core strategies the function uses, since the constants tie directly to choosing between them:
- For small samples relative to the population (
k << n): Generate random indices and retry if duplicates pop up. The chance of repeats is tiny here, so retry overhead is negligible, and we skip the memory cost of tracking selected elements. - For large samples (
kclose ton): Track selected elements (or equivalently, selectn-kelements to exclude) because duplicate picks become extremely likely—retries would turn into a huge performance drain.
1. The Threshold for Switching Strategies (k > n - k)
You’ve likely noticed the function switches tactics when k exceeds half of n. Here’s why this 50% threshold is the sweet spot:
- Probability Math: When
kcrosses the 50% mark, the odds of picking a duplicate index jump dramatically. For example, ifn=1000andk=600, by the 600th pick, only 400 unused indices remain—so there’s a 60% chance of hitting a duplicate. Retrying here would waste tons of cycles. - Performance Balance: Tracking selected elements uses
O(k)memory. Whenkis small, this memory overhead isn’t worth avoiding a few retries. But whenkis larger thann/2, it’s equally efficient to trackn-kelements (which is smaller thank) to exclude, and this eliminates the retry chaos. The 50% threshold is where the cost of retries overtakes the memory cost of tracking.
2. Retry Guard Constants (If Present)
Some implementations include a maximum retry limit before falling back to the tracking strategy, even for small k. This is a safety guard against edge cases—like a rare streak of duplicates from the random number generator. The constant here is chosen based on statistical likelihood: how many retries are "reasonable" before we decide the odds of getting a unique index are too low to keep trying. A limit of 10-20 ensures we never get stuck in an infinite loop in pathological scenarios, without adding noticeable overhead to normal use.
These constants aren’t guesswork—Python’s core devs ran benchmarks across hundreds of population and sample size combinations to find the thresholds that deliver the best overall speed and memory efficiency for real-world use cases.
内容的提问来源于stack exchange,提问作者tim-mccurrach




