GitHub

API reference for random.

Pseudo-random numbers as a service. Random is a reference, so effects draw numbers without declaring it; with_seed makes a run reproducible, and tests can provide their own RandomService.

The default service uses Python's random module and is not cryptographically secure.

Classes

Functions

next

next() -> Effect[float]

A random float in [0, 1).

Returns Effect[float]

def next() -> Effect[float]:
    """A random float in ``[0, 1)``."""
    return _random_with(lambda r: r.unsafe_next_double())

next_boolean

next_boolean() -> Effect[bool]

Returns Effect[bool]

def next_boolean() -> Effect[bool]:
    return _random_with(lambda r: r.unsafe_next_double() > 0.5)

next_int

next_int() -> Effect[int]

A random integer between -(2**53 - 1) and 2**53 - 1, both inclusive.

Returns Effect[int]

def next_int() -> Effect[int]:
    """A random integer between ``-(2**53 - 1)`` and ``2**53 - 1``, both inclusive."""
    return _random_with(lambda r: r.unsafe_next_int())

next_between

next_between(low, high) -> Effect[float]

A random float in [low, high).

ParameterTypeDescription
lowfloat
highfloat

Returns Effect[float]

def next_between(low: float, high: float) -> Effect[float]:
    """A random float in ``[low, high)``."""
    return _random_with(lambda r: _between(low, high, r.unsafe_next_double()))

next_int_between

next_int_between(low, high, *, half_open=False) -> Effect[int]

A random integer from ceil(low) to floor(high), inclusive unless half_open.

ParameterTypeDescription
lowfloat
highfloat
half_openbool = False

Returns Effect[int]

def next_int_between(low: float, high: float, *, half_open: bool = False) -> Effect[int]:
    """A random integer from ``ceil(low)`` to ``floor(high)``, inclusive unless
    ``half_open``."""
    low_int, high_int = math.ceil(low), math.floor(high)
    span = high_int - low_int + (0 if half_open else 1)
    return _random_with(lambda r: math.floor(r.unsafe_next_double() * span) + low_int)

shuffle

shuffle(elements) -> Effect[list[A]]

A shuffled copy of elements.

ParameterTypeDescription
elementsIterable[A]

Returns Effect[list[A]]

def shuffle[A](elements: Iterable[A]) -> Effect[list[A]]:
    """A shuffled copy of ``elements``."""

    def go(r: RandomService) -> list[A]:
        buffer = list(elements)
        for i in range(len(buffer) - 1, 0, -1):
            j = min(i, math.floor(r.unsafe_next_double() * (i + 1)))
            buffer[i], buffer[j] = buffer[j], buffer[i]
        return buffer

    return _random_with(go)

choice

choice(elements) -> Effect[A, NoSuchElementException]

A random element of elements. A non-empty tuple cannot fail; any other iterable fails with NoSuchElementException when empty.

ParameterTypeDescription
elementsIterable[A]

Returns Effect[A, NoSuchElementException]

def choice[A](elements: Iterable[A]) -> Effect[A, NoSuchElementException]:
    """A random element of ``elements``. A non-empty tuple cannot fail; any
    other iterable fails with ``NoSuchElementException`` when empty."""
    buffer = list(elements)
    if not buffer:
        return fail_sync(
            lambda: NoSuchElementException("Cannot select a random element from an empty array")
        )
    n = len(buffer)
    return _random_with(lambda r: buffer[min(n - 1, math.floor(r.unsafe_next_double() * n))])

with_seed

with_seed(seed) -> _WithSeed

Run an effect with a generator seeded by seed, restarted on each run: the same seed gives the same numbers (the same as in Effect)::

eff.pipe(random.with_seed("my-seed"))

ParameterTypeDescription
seedstr | float

Returns _WithSeed

def with_seed(seed: str | float) -> _WithSeed:
    """Run an effect with a generator seeded by ``seed``, restarted on each
    run: the same seed gives the same numbers (the same as in Effect)::

    eff.pipe(random.with_seed("my-seed"))
    """
    return _WithSeed(seed)