Skip to content

Support __index__() in getrandbits(), randbytes() and others #135378

Open
1 of 1 issue completed
Open
@serhiy-storchaka

Description

@serhiy-storchaka

Feature or enhancement

Support of the __index__() method in getrandbits() and randbytes() is inconsistent.

  • Random.getrandbits() supports __index__(), but SystemRandom.getrandbits() does not.
  • SystemRandom.randbytes() supports __index__(), but Random.randbytes() does not.

For consistence, both classes should support it.

sample() fails if its k argument is not integer. k should have __index__(), but it also should support comparison with integers and multiplication by list and integer. It is easy to make it more general, and only require __index__(). It will also produce more meaningful error.

binomialvariate() seems "working" with non-integer n argument, but the result is questionable. Passing non-integer value is most likely an error, and it would be better to detect it.

cc @rhettinger

Sub-issues

Activity

added
type-featureA feature request or enhancement
stdlibPython modules in the Lib dir
3.15new features, bugs and security fixes
on Jun 11, 2025
rhettinger

rhettinger commented on Jun 17, 2025

@rhettinger
Contributor

Personally, I don't think this is needed. It is just overhead that doesn't benefit real users.

In pure python code, we commonly do much less error checking on inputs than we do in C code.

serhiy-storchaka

serhiy-storchaka commented on Jun 19, 2025

@serhiy-storchaka
MemberAuthor

Yes, unfortunately it has a cost.

The worst case:

$ ./python -m timeit -s 'from random import randbytes' 'randbytes(1)'
Unpatched: 2000000 loops, best of 5: 145 nsec per loop
Patched:   2000000 loops, best of 5: 161 nsec per loop

It is less for larger argument:

$ ./python -m timeit -s 'from random import randbytes' 'randbytes(128)'
Unpatched: 500000 loops, best of 5: 616 nsec per loop
Patched:   500000 loops, best of 5: 633 nsec per loop

SystemRandom.getrandbits() is so slow, that the difference is insignificant.

$ ./python -m timeit -s 'import random; getrandbits = random.SystemRandom().getrandbits' 'getrandbits(1)'
Unpatched: 200000 loops, best of 5: 1.45 usec per loop
Patched:   200000 loops, best of 5: 1.47 usec per loop

For binomialvariate(), the effect is much weaker for n > 1.

$ ./python -m timeit -s 'from random import binomialvariate' 'binomialvariate()'
Unpatched: 1000000 loops, best of 5: 214 nsec per loop
Patched:   1000000 loops, best of 5: 229 nsec per loop
$ ./python -m timeit -s 'from random import binomialvariate' 'binomialvariate(2)'
Unpatched: 500000 loops, best of 5: 575 nsec per loop
Patched:   500000 loops, best of 5: 588 nsec per loop
$ ./python -m timeit -s 'from random import binomialvariate' 'binomialvariate(10)'
Unpatched: 200000 loops, best of 5: 1.11 usec per loop
Patched:   200000 loops, best of 5: 1.12 usec per loop

On other hand, operator.index() is already called multiple times for randrange() and randint().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.15new features, bugs and security fixesstdlibPython modules in the Lib dirtype-featureA feature request or enhancement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Support __index__() in getrandbits(), randbytes() and others · Issue #135378 · python/cpython

      Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

      Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant