Concepts / Working with Loops

Working with Loops

The loop controls how many calls occur; random.random() supplies the value for each call.

  • Programming

A New Value on Every Pass

A loop can call random.random() repeatedly so that each iteration receives a new pseudorandom float. The loop controls how many calls occur; random.random() supplies the value for each call. The values may look unpredictable, but they come from a deterministic sequence controlled by the random module's internal state.

python

This loop makes three calls to random.random(), one during each iteration. It therefore prints three floating-point values. The exact values are not specified in advance because they depend on the random module's current internal state.

Tracing the Loop State

What do you think happens?

The loop calls random.random() three times. What should happen across the iterations?

  • The same float is printed three times

  • Three new floats are printed, one per iteration

  • Only the final iteration produces a float

Reveal answer
Answer:

Three new floats are printed, one per iteration

Each call to random.random() returns the next value in the sequence. The random module's internal state changes with each call, so the next iteration receives a new pseudorandom value.

Iteration 1first callValue 1float in [0.0, 1.0)Iteration 2second callValue 2float in [0.0, 1.0)Iteration 3third callValue 3float in [0.0, 1.0)calls random.random()internal state advancescalls random.random()internal state advancescalls random.random()
What changes as the loop reaches each iteration and calls random.random()?

The important state change is not a variable shown in the loop body. The random module maintains internal state. Each call advances that state, and the changed state determines the next value. The function does not remember previous calls itself; the module's internal state controls the sequence.

The Half-Open Output Range

Definition

random.random() generates a pseudorandom float in the range [0.0, 1.0). The square bracket means that 0.0 is included. The parenthesis means that 1.0 is excluded.

0.0includedValues betweenpossible floats1.0excludedthrough the rangeapproaches but does not include
Which boundary values belong to the output range of random.random()?

The upper bound is exclusive: random.random() will not return exactly 1.0. This half-open range is useful when scaling the result. Multiplying by 100 produces a float in [0.0, 100.0). Multiplying by 6 and converting to an integer produces one of 0, 1, 2, 3, 4, or 5.

NotationMeaningFor random.random()
[Include the boundary0.0 can occur
)Exclude the boundary1.0 cannot occur

Reading the interval [0.0, 1.0)

A Three-Iteration Trace

Worked example

Following Three Calls

Trace a loop that calls random.random() once per iteration for three iterations.

  1. 1
    Iteration 1

    The first call returns the next pseudorandom float in the current sequence. That value is printed.

  2. 2
    Iteration 2

    The loop repeats. A second call returns a new float, because the random module's internal state has advanced after the first call.

  3. 3
    Iteration 3

    The loop repeats once more. A third call returns another float from the sequence, and that value is printed.

Result

The loop prints three floats. Every printed value is in [0.0, 1.0), and the exact sequence depends on the random module's internal state.

A useful trace records two things for every iteration: the iteration number and the value returned by that iteration's call. Do not expect a fixed list of literal values unless the seed and the number of earlier random calls are controlled.

Finding the Divergence Point

Expected 0.1Actual 0.7Expected later valuesActual later valuesfirst call differssequence continues from current state
Which iteration first differs when an expected sequence is compared with the generated sequence?

Suppose you expected the five-value sequence [0.1, 0.2, 0.3, 0.4, 0.5], but the loop produced [0.7, 0.8, 0.9, 0.6, 0.5]. The first divergence is at the first call: the generated value is 0.7 instead of 0.1. The divergence occurs at random.random(), where the pseudorandom value is generated, not elsewhere in the loop.

Reproducible Loop Runs

Use random.seed() before the loop when testing or debugging requires the same sequence to be reproduced. Setting the same seed before the same sequence of calls produces identical sequences. Without resetting the seed, repeated runs can produce different sequences.

python

The important behavior in this example is that the seed is set before the loop begins. If the same seed is set again before the same three calls, the sequence is reproducible. The code still generates pseudorandom floats, but the starting internal state is controlled.

Common Loop Mistakes

  • Common mistake

    Expecting random.random() to return the same fixed sequence on every run without setting a seed.

    What it looks like

    Running the same loop twice and assuming its printed values must match.

    Why it fails

    Different runs can begin with different internal states, so they can produce different pseudorandom sequences.

    Do this instead

    Call random.seed() before the loop when you need reproducible output.

  • Common mistake

    Treating 1.0 as a possible result.

    What it looks like

    Assuming the range includes both 0.0 and 1.0.

    Why it fails

    The interval is [0.0, 1.0): 0.0 is included, but 1.0 is excluded.

    Do this instead

    Read the square bracket and parenthesis separately before reasoning about possible values.

  • Common mistake

    Looking for the divergence somewhere after the random call.

    What it looks like

    Blaming the loop after seeing a value that differs from an expected list.

    Why it fails

    The divergence begins at the random.random() call that generated the unexpected value.

    Do this instead

    Compare expected and actual values starting with the first call, then check the seed and the number of earlier calls.

  • Common mistake

    Assuming a loop reuses one random value automatically.

    What it looks like

    Expecting every iteration to print the first value generated.

    Why it fails

    Each iteration calls random.random() again, and each call returns the next value in the sequence.

    Do this instead

    Count the calls: one call per iteration produces one new value per iteration.

Check Your Prediction

EASY

A loop calls random.random() five times. Before running it, predict how many floats will be printed, whether 0.0 is allowed, whether 1.0 is allowed, and what must be controlled if you want to reproduce the same sequence in a second run.

Hints
  • Count one random.random() call for each loop iteration.
  • Use the notation [0.0, 1.0) to determine the boundary behavior.
  • Reproducibility depends on setting the seed before the calls.
Worked example

Practice Answer

Determine the behavior of a five-iteration loop that calls random.random() once per iteration.

  1. 1
    Number of outputs

    There is one call during each of five iterations, so the loop prints five floats.

  2. 2
    Range

    Each float is in [0.0, 1.0). Therefore 0.0 is included and 1.0 is excluded.

  3. 3
    Reproduction

    Set the same seed before the same sequence of calls if the second run must produce the same sequence.

Result

Five pseudorandom floats are printed. Each is at least 0.0 and less than 1.0, and the sequence can be reproduced by controlling the seed before the loop.

Key Takeaways

  1. 1
    Each call to random.random() returns a pseudorandom float in [0.0, 1.0).
  2. 2
    The range includes 0.0 but excludes 1.0.
  3. 3
    A loop calling random.random() once per iteration produces one new value per iteration.
  4. 4
    The random module's internal state advances with each call and determines the next value.
  5. 5
    Use random.seed() before the loop to reproduce a sequence for testing or debugging.

At a glance

  • random.random() generates pseudorandom floats in the half-open interval [0.0, 1.0).
  • A repeated call advances the random module's internal state and produces the next value in its sequence.
  • A loop makes the number of calls easy to count: one call per iteration means one generated float per iteration.
  • When actual output differs from an expected sequence, the first divergence occurs at a random.random() call.
  • Setting the same seed before the same calls makes the sequence reproducible.

Related concepts

More concepts starting with W