我想構建一個系統,其中每個其他對象都使用一個基類。每個基礎對象在內部都有一個_fields
字典,其中基類的實現可以存儲其信息。結合__setattr__和__getattr__導致無限循環
基類的實現很簡單:
class A(object):
def __init__(self, fields=dict()):
self._fields = fields
類的實現可以設置在__init__
調用其super()
領域。
我想補充說的是,這些字段可以作爲屬性訪問,而不必將@property
修飾器添加到一大堆函數中。我已經重寫了__getattr__
用於此目的的基類,像這樣:
class A_impl(A):
def __init__(self):
super(A_impl, self).__init__(
fields=dict(
val_1="foo",
val_2="",
val_3="bar",
)
)
通過它創建該類的實現提供:
class A(object):
def __init__(self, fields=dict()):
self._fields = fields
def __getattr__(self, name):
if hasattr(self, name):
return object.__getattribute__(self, name)
elif name in self._fields:
return self._fields.get(name)
else:
raise AttributeError
現在對於這個類實現可以這樣工作你選擇做:
test = A_imp()
print test.val_1
print test.val_2
print test.val_3
它返回
foo
bar
我甚至可以通過@property
裝飾覆蓋此,改變類,像這樣:
class A_impl(A):
def __init__(self):
super(A_impl, self).__init__(
fields=dict(
val_1="foo",
val_2="",
val_3="bar",
)
)
@property
def val_1(self):
return self._fields.get('val_1') + "_getter"
,讓我來操縱數據的回報。唯一的問題是,如果我想能夠設置這些字段變量之一,我必須實現描述符設置函數,這也需要我做屬性描述符,它創造了很多重複的工作(即我必須定義我的所有字段描述這是我想避免在這裏。
我實現了__setattr__
功能的基類來解決地方如果我手動實現它應該在默認這是self._field[name] = value
選擇一個描述符setter函數問題基類現在看起來像這樣(類似於__getattr__
):
class A(object):
def __init__(self, fields=dict()):
self._fields = fields
def __getattr__(self, name):
if hasattr(self, name):
return object.__getattribute__(self, name)
elif name in self._fields:
return self._fields.get(name)
else:
raise AttributeError
def __setattr__(self, name, value):
if hasattr(self, name):
object.__setattr__(self, name, value)
elif name in self._fields:
self._fields[name] = value
else:
raise AttributeError
現在,如果我再次運行相同的代碼測試:
test = A_imp()
print test.val_1
print test.val_2
print test.val_3
,瞬間陷在一個無限循環,它開始在__setattr__
但跳進右後__getattr__
,並保持該循環。
我一直在閱讀很多關於這個stackoverflow的問題,無法弄清楚,這就是爲什麼我建立這個測試用例,以清楚地弄清楚它。希望有人能夠爲我澄清這一點,並幫助我解決問題。
'hasattr'是不必要的。 – o11c