首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使一个对象具有像随机数生成器这样的接口,但它实际上生成了一个指定的序列?

如何使一个对象具有像随机数生成器这样的接口,但它实际上生成了一个指定的序列?
EN

Stack Overflow用户
提问于 2022-03-29 00:34:02
回答 6查看 3.7K关注 0票数 16

我想要构造一个像随机数生成器一样工作的对象,但是按照指定的顺序生成数字。

代码语言:javascript
复制
# a random number generator
rng = lambda : np.random.randint(2,20)//2

# a non-random number generator
def nrng():
    numbers = np.arange(1,10.5,0.5)
    for i in range(len(numbers)):
        yield numbers[i]

for j in range(10):
    print('random number', rng())
    print('non-random number', nrng())

以上代码的问题,我不能在最后一行中调用nrng,因为它是一个生成器。我知道,重写上面代码的最简单的方法是简单地循环非随机数,而不是定义生成器。我更愿意让上面的例子起作用,因为我正在处理大量的代码,其中包括一个函数,它接受一个随机数生成器作为参数,并且我想在不重写整个代码的情况下添加传递非随机数序列的功能。

编辑:我在评论中看到了一些困惑。我知道python的随机数生成器会产生伪随机数。这篇文章是关于用一个数字生成器代替一个伪随机数生成器,该生成器从非随机用户指定的序列生成数字(例如,生成数字序列1,1,2,2,1,0,1的生成器,如果我愿意的话)。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2022-03-29 01:45:08

编辑:

要做到这一点,最干净的方法是使用lambda包装对next(nrng)的调用,这是@GACy20中的一个很好的注释:

代码语言:javascript
复制
def nrng_gen():
    yield from range(10)

nrng = nrng_gen()

nrng_func = lambda: next(nrng)

for i in range(10):
    print(nrng_func())

原来的答案:

如果您希望您的对象保持状态,并且看起来像一个函数,请使用__call__方法创建一个自定义类。

例如:

代码语言:javascript
复制
class NRNG:
    def __init__(self):
        self.numbers = range(10)
        self.state = -1
    def __call__(self):
        self.state += 1
        return self.numbers[self.state]
        
nrng = NRNG()


for i in range(10):
    print(nrng())

但是,除非绝对必要,否则我不建议这样做,因为它掩盖了nrng保持状态的事实(尽管从技术上讲,大多数rng都在内部保持状态)。

最好通过调用next来使用带有yield的常规生成器,或者编写自定义迭代器(也是基于类的)。这些工具将适用于类似for循环和其他用于迭代的python工具(比如优秀的itertools包)。

票数 15
EN

Stack Overflow用户

发布于 2022-03-29 00:42:17

您可以使用生成器或迭代器调用next()作为参数,从其中提取一个元素。预先将生成器保存到变量允许您多次执行此操作。

代码语言:javascript
复制
# make it a generator
def _rng():
    while True:
        yield np.random.randint(2,20)//2

# a non-random number generator
def _nrng():
    numbers = np.arange(1,10.5,0.5)
    for i in range(len(numbers)):
        yield numbers[i]

rng = _rng()
nrng = _nrng()
for j in range(10):
    print('random number', next(rng))
    print('non-random number', next(nrng))
票数 19
EN

Stack Overflow用户

发布于 2022-03-29 00:52:00

np.random.randint可以记住它生成的最后一个数字,因为它是np.random.RandomState类的函数。Numpy只是对类方法进行化名,这样就可以从np.random模块直接访问它,而不是让您通过类访问它。

知道了这一点,您可以编写自己的类,如下所示:

代码语言:javascript
复制
class NotRandom:

    numbers = np.arange(1,10.5,0.5)
    last_index = -1

    @classmethod
    def nrng(cls):
        cls.last_index += 1
        if cls.last_index < len(cls.numbers):
            return cls.numbers[cls.last_index]
        # else:
        return None

# Create an alias to the classmethod
nrng = NotRandom.nrng      # Note this is OUTSIDE the class

然后,你可以:

代码语言:javascript
复制
print(nrng())    # 1.0
print(nrng())    # 1.5
print(nrng())    # 2.0

如果您希望能够拥有多个并发nrng实例,则可以使nrng()成为实例方法,而不是类方法:

代码语言:javascript
复制
class NotRandom:
    def __init__(self):
        self.numbers = np.arange(1,10.5,0.5)
        self.last_index = -1

    def nrng(self):
        self.last_index += 1
        if self.last_index < len(self.numbers):
            return self.numbers[self.last_index]
        # else:
        return None

# Create an object. Then create an alias to its method
nrng = NotRandom().nrng 

然后,您可以使用nrng()来引用绑定到您创建的NotRandom实例的方法。如果您想要另一个实例,您也可以这样做:

代码语言:javascript
复制
another_notrandom = NotRandom()
nrng2 = another_notrandom.rng

print(nrng())    # 1.0
print(nrng())    # 1.5

print(nrng2())   # 1.0

print(nrng())    # 2.0

print(nrng2())   # 1.5
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71655179

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档