我想創建一個類,可以用** kwargs初始化並具有每個字段的默認值的系統。下面是一些代碼代表什麼,我試圖做的:Python類的繼承:動態子類初始化與自己和父母的默認值和初始化方法
Gen2item1 = Gen2()
Gen2item2 = Gen2(p_var_1 = "different name", G2_var_1 = 666)
Gen2item1將被初始化爲所有默認值:
-
設置幾個實例後
class Parent(object): #should only have p_var fields
DEFAULTS = {
"p_var_1" : "my name",
"p_var_2" : 2
}
def __init__(self, **kwargs):
for key in DEFAULTS:
#Also include check for list type and copy, not assign
if key in kwargs:
setattr(self, key, kwargs[key])
else:
setattr(self, key, self.DEFAULTS[key])
#Check for super being 'object' - problems?
#if not super() == object:
# super().__init__(**kwargs)
class Gen1(Parent): #should have p_var and G1_var fields
DEFAULTS = {
"G1_var_1" : "Generation 1",
"G1_var_2" : []
}
#redefining only in case if Parent can't check for super
def __init__(self, **kwargs):
for key in DEFAULTS:
#Also include check for list type and copy, not assign
if key in kwargs:
setattr(self, key, kwargs[key])
else:
setattr(self, key, self.DEFAULTS[key])
#check whether super() is object
super().__init__(**kwargs) #pass all args to parent init
class Gen2(Gen1): #should have p_var, G1_var and G2_var fields
DEFAULTS = {
"G2_var_1" : 1337,
"G2_var_2" : (10,4)
}
#After Gen1, redefining __init__ shouldn't be necessary
使
但Gen2item1會有不同的p_var_1和G2_var_1值,其餘部分相同。 然而,由於 '默認' 兒童類被覆蓋,則Gen2item1值:
- Gen2item1.p_var_1是666
- Gen2item1.p_var_2是(10,4)
被設置三種次,按每代(級),並且G1_var
或p_var
值未設置。對於Gen2item2,所有三代__init__
的G2_var_1設置爲666,G2_var_2設置爲(10,4)。
因此,底線的問題是關於一種方法,使一些「默認」字段(字典)每個類產生,因此:
- 在調用子類通過
item = subclass()
的__init__
,它會搶來自kwargs
的參數取決於'默認'字典的鍵, - 通過
setattrib(self, key, value)
設置其自己的字段,如果來自默認值的鍵存在,則從kwargs中取值,否則從默認值中取值,以及 - 在通過
super()__init__(**kwargs)
將kwargs傳遞給它的父輩的init時調用它。
父然後將其代的字典定義的子類的同一個實例相同的方式,默認值,調用並傳遞給自己的父母__init__
,依此類推,直到父object
,在這種情況下, super().__init__
根本不會被調用/傳遞參數。
我已經閱讀了關於metaclasses,這似乎矯枉過正,和got my hopes high on this,它有一個單獨的父母和子類的實例。
有沒有一種方法來實現這樣的東西沒有元類?將默認值存儲在外部的全球字典中是否會更好?(在這種情況下,我們將讚賞一些有關尋址的幫助),還是有辦法建立一個工廠?
解決編輯:
的__init_subclass__
作品,差不多我想要做什麼,只要它也定義__init__
的類被初始化(爲我的項目的具體細節)。這是我的問題的答案,並提供了一些有用的信息,以瞭解如何在我的項目中實現我想要的設置。我認爲定義一個classmethod就足夠了,它可以設置合適的__init__
並在定義類時運行它(這是新的__init_subclass__
似乎可以幫助的),但是至少有一些向後兼容性,它似乎元類是做到這一點的方法。
這適用於設置默認值,但似乎我仍然必須定義'__init__'來更改創建實例時的值,因爲在執行類似'g1 = Gen1(G1_var_1 =「asdf之類的操作時,使用此代碼時會引發TypeError 「)' – DZHEX
通過在'__init_subclass__'中設置'__init__'創建者函數,似乎我想要做的工作。經過一些測試,如果沒有問題出現,將標記爲答案。 – DZHEX
是的,這個例子太骨架了。它只是爲了顯示'__init_subclass__'方法。你是對的:'__init_subclass__'被調用來創建子類,但如果你想在實例化中傳遞參數(位置或名字),則需要'__init__'。我更新了代碼。 –