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).
| Parameter | Type | Description |
|---|---|---|
low | float | |
high | float |
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.
| Parameter | Type | Description |
|---|---|---|
low | float | |
high | float | |
half_open | bool = 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.
| Parameter | Type | Description |
|---|---|---|
elements | Iterable[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.
| Parameter | Type | Description |
|---|---|---|
elements | Iterable[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) -> _WithSeedRun 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"))
| Parameter | Type | Description |
|---|---|---|
seed | str | 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)