为Python程序中的参数分配随机值
我需要在 __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 秒,但结果仍然相同。
I need to assign a default random value in __init__()
. For example:
import math
import random
class Test:
def __init__(self, r = random.randrange(0, math.pow(2,128)-1)):
self.r = r
print self.r
If I create 10 instances of Test, they all get the exact same random value. I don't understand why this is happening. I know I can assign the random value inside the __init__()
, but I am curious why this is happening. My first guess was that the seed is the current time and objects are being created too close together, and, as a result, get the same random value. I created objects 1 second apart, but still same result.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
默认参数的值是在创建函数时设置的,而不是在调用函数时设置的 - 这就是为什么它每次都是相同的。
处理此问题的典型方法是将默认参数设置为 None 并使用 if 语句进行测试。
The value of the default parameter is being set at the time the function is created, not when it is called - that's why it's the same every time.
The typical way to deal with this is to set the default parameter to
None
and test it with anif
statement.random.randrange(0, math.pow(2,128)-1)
在定义函数时计算,而不是在调用函数时计算。代替使用
。
The
random.randrange(0, math.pow(2,128)-1)
is evaluated when the function is defined, not when it is called.Use
instead.
当您将表达式放入构造函数标头(而不是构造函数主体)中时,它只会被计算一次。
在身体里试试这个:
When you put the expression inside the constructor header (instead of the constructor body) it only gets evaluated once.
Try this in the body:
所有类实例的参数值都相同的原因是,当它所属的方法定义被编译为
class
语句执行的一部分时,它的默认值仅确定一次。虽然这不是它的设计用途,但您可以使用标题为 自动初始化的配方 20.14实例属性来自有点过时的Python Cookbook,第二版来实现您想要做的事情。
这是它应用于您问题中的示例代码:
示例输出:
它的工作原理如下:
配方中的
auto_attr
类称为 描述符。其中之一被分配给名为r
的Test
class 属性。第一次使用self.r
在Test
实例中访问此属性时,Python 会注意到它绑定到描述符并调用其__get__()
方法,将Test
实例作为obj
参数。描述符的
__get__()
方法调用关联的工厂函数,并将结果分配给具有相同名称的实例属性,以便通过实例对该属性的所有进一步引用都将获取其实际值而不是Test
类的auto_attr
描述符。The reason all your class instances have the same value for the argument is because its default value is determined only once, when the method definition it is part of is compiled as part of the
class
statement's execution.Although this is not the use it was designed for, you could use Recipe 20.14 titled Automatic Initialization of Instance Attributes from the somewhat dated Python Cookbook, 2nd Edition to achieve what you want to do.
This is it applied to the sample code in your question:
Sample output:
Here's how it works:
The
auto_attr
class from the recipe is a called a descriptor. One of them is assigned to aTest
class attribute namedr
. The first time you access this attribute in an instance ofTest
usingself.r
, Python notices it's bound to a descriptor and calls its__get__()
method with theTest
instance as anobj
argument.The descriptor's
__get__()
method calls the associated factory function and assigns the result to an instance attribute with the same name, so that all further references to that attribute through the instance will get its actual value instead of theTest
class'sauto_attr
descriptor.