Concepts / Choosing Random Elements from a List with random.choice()

Choosing Random Elements from a List with random.choice()

random.randint(low, high) generates a random integer within an inclusive range, including both the low and high endpoints.

  • Programming
Interactive lab

Try it: random.seed and the Mersenne Twister

Python's random module is a deterministic generator: random.seed(n) sets the Mersenne Twister's internal state, and every random(), randint(), choice() and shuffle() consumes 32-bit outputs from it in order — so the same seed replays the same sequence and a different seed gives a different one.

How it works

  1. random.seed(n) splits |n| into 32-bit words and runs MT19937's init_by_array, filling the 624-word state.
  2. Each 32-bit output takes the next state word and tempers it; after 624 words the whole state is regenerated (the twist).
  3. random() joins two outputs: with , , a float in [0.0, 1.0).
  4. randint(a, b) = a + _randbelow(b − a + 1); choice(seq) = seq[_randbelow(len(seq))]; _randbelow(n) keeps the top n.bit_length() bits and rejects values ≥ n.
  5. shuffle walks i from the end down to 1 and swaps x[i] with x[_randbelow(i + 1)].
  6. Replaying the program with a second seed shows where the sequences agree or first diverge.

Default run (11 steps): A program of 5 random-module calls, run after random.seed(42). … Replay with random.seed(42): every result is identical — same seed, same state, same sequence.

Simplified: Seeds are non-negative integers below (one key word), at most 8 calls, randint bounds within ±1000, and lists of up to 8 simple items. Only mt[0..3] and mt[623] of the 624-word state vector are shown (abbreviated). Everything else follows CPython 3.12's random module exactly.

Educational simulation

Loading the simulation…

A Number from a Range

Suppose a program needs one random integer from 5 through 10. The function random.randint(5, 10) can produce any integer from that range, including both boundary values. The result can change from one call to another, so the program must be prepared for every allowed outcome.

What do you think happens?

Which values can random.randint(5, 10) return?

  • 5, 6, 7, 8, and 9

  • 6, 7, 8, 9, and 10

  • 5, 6, 7, 8, 9, and 10

  • Only 5 and 10

Reveal answer
Answer:

5, 6, 7, 8, 9, and 10

randint() includes both the low endpoint and the high endpoint. There are six possible integers, and each has an equal 1-in-6 chance on any given call.

Tracing the Endpoints

5possible result6possible result7possible result8possible result9possible result10possible resultnextnextnextnextnext
Which integer outcomes belong to random.randint(5, 10), including what happens at both endpoints?

The word inclusive is the key to using randint() correctly. In random.randint(low, high), low is allowed and high is also allowed. Therefore, random.randint(5, 10) has six possible outcomes: 5, 6, 7, 8, 9, and 10. Each outcome has an equal 1-in-6 chance on any one call.

python
Output
One possible output is:
7

Another call may produce a different value from the same allowed set: 5, 6, 7, 8, 9, or 10.

randint() and range()

ExpressionLower endpointUpper endpointPossible values in the example
random.randint(5, 10)IncludedIncluded5, 6, 7, 8, 9, 10
range(5, 10)IncludedExcluded5, 6, 7, 8, 9

randint() includes its high value, while range() excludes its high value.

randint(5, 10)5 through 1010includedrange(5, 10)5 through 910excludedincludes upper endpointstops before upper endpoint
Which values can each expression produce, and what happens to the upper endpoint?

From a List Index to an Element

A random integer can be used as a position when a program needs to select an element from a list. The important boundary question is whether the integer range matches the list's valid positions. Because randint() includes its upper bound, giving it an upper bound that is one greater than the final valid position can request a position that does not exist.

0redrandint(0, 4)one valid position1blue2green3yellow4purplemay selectmay selectmay selectmay selectmay select
How do inclusive endpoints map to the valid zero-based positions of a list?
Code walkthrough
import random

colors = ["red", "blue", "green", "yellow", "purple"]
position = random.randint(0, 4)
selected_color = colors[position]
print(selected_color)
  1. 1
    Import the random module before calling randint().
  2. 2
    Create a list with five elements.
  3. 3
    Generate an integer from 0 through 4. The upper endpoint 4 is included.
  4. 4
    Use the generated position to select one element from the list.
  5. 5
    Print the selected element.
ApproachWhat is produced firstWhat happens next
random.randint() with a list positionA random integerThe integer is used as a list position
random.choice()A selected list elementThe element can be used directly

randint() generates a number; choice() is named for selecting an element directly.

Practical Random Integers

Worked example

Assigning a Random Number

A program needs one random integer from 1 through 6 for a numbered selection.

  1. 1
    Import

    Import the random module before calling randint().

  2. 2
    Set the boundaries

    Use 1 as the low value and 6 as the high value because randint() includes both endpoints.

  3. 3
    Generate

    Call random.randint(1, 6) and store the result.

  4. 4
    Use the result

    The stored integer can be printed or used by later program logic.

Result

The variable contains one integer from 1, 2, 3, 4, 5, or 6.

python
Requested range1 through 6randint(1, 6)inclusive boundsRandom integer1, 2, 3, 4, 5, or 6translate boundsreturns
How does a real-world request become a randint() call and then a usable integer?

Mistakes with randint()

Before
number = random.randint(1, 6)

The function is called before the random module has been imported.

After
import random

number = random.randint(1, 6)

The module is imported before randint() is called.

randint(10, 5)reversed boundsrandint(0, 5)upper bound may exceedfinal positionrandint(5, 10)low before highrandint(0, 4)matches positions 0 through4correct the ordercorrect the inclusive upper bound
What changes when the module is imported and the randint() bounds are chosen deliberately?
  • Common mistake

    Forgetting to import the random module

    What it looks like
    number = random.randint(1, 6)
    Why it fails

    The random module must be imported before randint() is called.

    Do this instead

    Write import random before using random.randint().

  • Common mistake

    Assuming the high value is excluded

    What it looks like
    random.randint(5, 10) is treated as though 10 cannot occur.
    Why it fails

    randint() includes both the low and high endpoints.

    Do this instead

    Include the high value among the possible results.

  • Common mistake

    Passing the bounds in the wrong order

    What it looks like
    random.randint(10, 5)
    Why it fails

    The intended low and high values have been reversed.

    Do this instead

    Pass the lower boundary first and the higher boundary second.

  • Common mistake

    Using non-integer arguments

    What it looks like
    random.randint(1.5, 6.5)
    Why it fails

    The parameters for randint() should be integers.

    Do this instead

    Use integer values for both boundaries.

  • Common mistake

    Using an upper list position that is one too high

    What it looks like

    A list with positions 0 through 4 is paired with random.randint(0, 5).

    Why it fails

    The high endpoint is included, so 5 can be generated even though the intended positions stop at 4.

    Do this instead

    Set the upper bound to the final valid position.

Practice the Boundaries

EASY

Write a Python statement that generates one random integer from 20 through 30, including both 20 and 30. Then identify the mistake in random.randint(0, 5) when it is used to select a position from a five-element list whose positions run from 0 through 4.

Hints
  • Import the random module before calling the function.
  • randint() includes the high value.
  • For the five-element list example, the highest valid position is 4.

Key Takeaways

  1. 1
    random.randint(low, high) returns a random integer from low through high.
  2. 2
    Both endpoints are included, so random.randint(5, 10) can return 5, 6, 7, 8, 9, or 10.
  3. 3
    Unlike randint(), range() excludes its upper endpoint.
  4. 4
    Import random first, use integer arguments, and place the lower bound before the higher bound.
  5. 5
    When using a generated number as a list position, make the inclusive upper bound match the final valid position.

At a glance

  • randint() generates random integers with inclusive lower and upper boundaries.
  • The upper-bound rule differs from range(), whose upper endpoint is excluded.
  • A random integer can serve as a list position only when its bounds match the valid positions.
  • Import random, use integer arguments, and check the order and meaning of both bounds.

More concepts starting with C