gpt4 book ai didi

python - 如何用自己的生成器覆盖Python的随机数?

转载 作者:行者123 更新时间:2023-12-02 02:05:43 24 4
gpt4 key购买 nike

docs对于Python的random,它指出可以通过重写random()方法来“使用您自己的基本生成器”。假设我有一个自定义生成器,它均匀地输出半开范围 [0.0, 1.0) 内的随机 float ,即就像 random() 一样。

  • 我该如何用我自己的 Python 替换?

此外,假设替代品是一个基于自然熵源构建的真正的随机生成器。

  • 这是否意味着我可以在给定数组上使用类的其他部分,例如 random.choice() 并声明所选元素是真正随机的?

最佳答案

Python 的 random 模块实际上是围绕 random.Random 类型构建的。各种“随机函数”(例如random.random)仅使用该类型的默认实例。

要创建您自己的随机数生成器,只需对 random.Random 进行子类化并替换其 random方法即可。虽然基本功能并不严格要求,但强烈建议也调整 seedgetstatesetstate 方法。

class RangeRandom(Random):
"""
Example "random" number generator that provides numbers from a uniform sequence
"""
def __init__(self, resolution=100):
self._pos = 0
self._resolution = resolution

def random(self) -> float:
self._pos = (self._pos + 1) % self._resolution
return self._pos / self._resolution

def getstate(self):
return self._pos, self._resolution

def setstate(self, state) -> None:
self._pos,self._resolution = state

def seed(self, a) -> None:
self._pos = int(a) % self._resolution

值得注意的是,定义random方法足以使所有其他方法使用相同的底层“随机性”。例如,choicerandint 使用的随机整数将根据 random 方法绘制:

>>> rand = RangeRandom()
>>> vals = [1, 2, 3, 4]
>>> [rand.choice([1, 2, 3, 4]) for _ in range(5)]
[2, 4, 2, 4, 2, 4]

值得指出的是,虽然实现随机已经足够了random.Random then uses an internal helper to convert the random floats to random integers ;这本质上是有损的,因为 float 精度有限。如果随机数生成器允许,建议还实现 _randbelow 或至少 getrandbits

random.getrandbits(k)

Returns a non-negative Python integer with k random bits. This method is supplied with the MersenneTwister generator and some other generators may also provide it as an optional part of the API. When available, getrandbits() enables randrange() to handle arbitrarily large ranges.

未公开的方法_randbelow必须采用整数n并返回区间[0, n)中的随机整数。

class ArbitraryRangeRandom(RangeRandom):
"""
Example "random" number generator for floats/ints from a uniform sequence
"""
def _randbelow(self, n: int) -> int:
self.random() # advance the RNG
if n == 0:
return 0
elif n <= self._resolution:
return self._pos % n
else:
return self._pos * (n // self._resolution)
>>> rand = RangeRandom()
>>> vals = [1, 2, 3, 4]
>>> # explicit int support provides better resolution/spacing
>>> print([rand.choice([1, 2, 3, 4]) for _ in range(5)])
[2, 3, 4, 1, 2]

关于python - 如何用自己的生成器覆盖Python的随机数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68488484/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com