的原因,你的所有的類實例有參數相同的值,因爲它的默認值被確定只有一次,當方法定義,它是被編譯部分作爲class
聲明執行的一部分。
儘管這不是它的設計用途,但您可以使用的配方 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。其中一個被分配到Test
類別屬性名稱r
。第一次在Test
使用self.r
的實例中訪問此屬性時,Python會注意到它與描述符綁定,並將其__get__()
方法與Test
實例作爲obj
參數進行調用。
描述符的__get__()
方法調用相關的工廠功能和結果分配給具有相同名稱的實例屬性,以便於通過實例該屬性的所有引用會得到它的實際價值,而不是Test
類的auto_attr
的描述。
但是,當表達式用於定義構造函數參數的默認值時爲true,但一般而言,構造函數中的其他表達式在每次調用初始化實例時都會被計算。 – martineau
@martineau:你指的是什麼其他表情? –
@Ethan Furman:任何不用於定義構造函數參數默認值的表達式在每次被調用時都會被評估,比如那些出現在方法本體內部的表達式 - 比如本答案中所示。 – martineau