将随机值分配给python程序中的参数

时间:2011-06-24 02:44:29

标签: python random parameters init

我需要在__init__()中分配默认随机值。例如:

import math
import random
class Test:
    def __init__(self, r = random.randrange(0, math.pow(2,128)-1)):
        self.r = r
        print self.r

如果我创建10个Test实例,它们都会获得完全相同的随机值。我不明白为什么会这样。我知道我可以在__init__()内分配随机值,但我很好奇为什么会这样。我的第一个猜测是种子是当前时间,并且对象被创建得太近,因此,获得相同的随机值。我创建的对象间隔1秒,但结果仍然相同。

4 个答案:

答案 0 :(得分:15)

默认参数的值是在创建函数时设置的,而不是在调用函数时设置的 - 这就是每次都相同的原因。

处理此问题的典型方法是将默认参数设置为None并使用if语句对其进行测试。

import math
import random
class Test:
     def __init__(self, r = None):
             if r is None:
                 r = random.randrange(0, math.pow(2,128)-1)
             self.r = r
             print self.r

答案 1 :(得分:4)

在定义函数时评估random.randrange(0, math.pow(2,128)-1),而不是在调用函数时评估。{/ p>

使用

class Test:
    def __init__(self, r = None):
        if r is None:
            r = random.randrange(0, math.pow(2,128)-1)
        self.r = r
        print self.r

代替。

答案 2 :(得分:1)

当您将表达式放在构造函数头(而不是构造函数体)中时,它只会被评估一次。

在体内试试这个:

self.r = random.randrange(0,math.pow(0,128)-1)

答案 3 :(得分:1)

所有类实例具有相同的参数值的原因是因为它的默认值只确定一次,因为它所属的方法定义是作为class语句执行的一部分编译的。

虽然这不是它的设计用途,但您可以使用标题为Automatic Initialization of Instance Attributes的Recipe 20.14来实现您想要做的事情。

这适用于您问题中的示例代码:

class AutoAttr(object):
    def __init__(self, name, factory, *args, **kwds):
        self.data = name, factory, args, kwds
    def __get__(self, obj, cls=None):
        name, factory, args, kwds = self.data
        setattr(obj, name, factory(*args, **kwds))
        return getattr(obj, name)

import math
import random

class Test(object):
    r = AutoAttr('r', random.randrange, 0, math.pow(2,128)-1)  # default value
    def __init__(self, r=None):
        if r is not None:  # argument value supplied to override default?
            self.r = r
        print format(self.r, ',d')

for i in xrange(5):
    Test()
Test(42)  # override default random initial value

示例输出:

282,608,676,427,101,189,083,121,399,193,871,110,434
211,475,719,281,604,076,410,306,973,803,289,140,631
86,842,148,927,120,143,765,936,219,265,140,532,918
41,767,122,731,332,110,507,836,985,804,081,250,336
97,993,619,669,833,151,963,441,072,354,430,500,011
42

以下是它的工作原理:

食谱中的auto_attr类称为Python Cookbook, 2nd Edition。其中一个分配给名为Test的{​​{1}} 属性。第一次使用rTest的实例中访问此属性时,Python会注意到它绑定到描述符并使用self.r实例调用其__get__()方法作为{ {1}}论证。

描述符的Test方法调用关联的工厂函数并将结果分配给具有相同名称的实例属性,以便通过实例对该属性的所有进一步引用将获得其实际值而不是obj类的__get__()描述符。