所有类实例的参数值都相同的原因是,它的默认值只确定一次,当它所属的方法定义被编译为 class 语句执行的一部分时。
虽然这不是它的设计用途,但您可以使用标题为 Automatic Initialization of Instance Attributes 的配方 20.14 来自有点过时的 Python Cookbook, 2nd Edition 来实现您想要做的事情。
这是应用于您问题中的示例代码:
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 类称为descriptor。其中一个被分配给名为r 的Test class 属性。当您第一次使用 self.r 在 Test 的实例中访问此属性时,Python 注意到它已绑定到一个描述符并使用 Test 实例作为 obj 参数调用其 __get__() 方法。
描述符的__get__() 方法调用关联的工厂函数并将结果分配给具有相同名称的instance 属性,以便通过实例对该属性的所有进一步引用都将获得其实际值而不是 Test 类的 auto_attr 描述符。