字典屬性化訪問Dict2Obj & __setattr__的思考
阿新 • • 發佈:2020-11-14
class B:
def __setattr__(self,key,value):
pass
raise NotImplementedError
類方法__setattr__覆蓋父類方法後,如果為pass, raise NotImplementedError之類的,則例項不能設定任何屬性
pass不會報錯,raise NotImplementedError會拋異常
但是類可以繼續增加屬性,__setattr__為例項方法
但是例項的__dict__為一個空dict,這是__new__方法建立例項的時候已經建立好的,在__setattr__之前,
所以可以通過直接操作例項的__dict__來變相新增屬性
class B:
def __setattr__(self,key,value):
raise NotImplementedError('{} can\'t set attribute!'.format(self))
b=B()
print(b.__dict__)
b.a=33
class B:
def __setattr__(self,key,value):
raise NotImplementedError('{} can\'t set attribute! '.format(self))
b=B()
print(b.__dict__)
b.__dict__['v']=33
print(b.__dict__)
print(b.v)
class Dict2Obj(object):
def __init__(self,d:dict):
# self._dict=d
self.__dict__={'_dict':d}
# self.b=33
def __getattr__(self,item):
try:
# def __setattr__: pass,I.__dict__ == {},取self._dict時,又會呼叫__getattr__
return self._dict[item]
# return getattr(self._dict,item) # AttributeError: 'dict' object has no attribute 'b'
# return getattr(self,item) # 本身就是.訪問
except KeyError:
raise AttributeError('Attribute {!a:} not found!'.format(item))
def __setattr__(self,key,value):
pass
上面的會產生迴圈呼叫
self._dict=d
self.__dict__={'_dict':d}
self.b=33
都會呼叫__setattr__,不會產生作用
getattr(object,name,default=None) 內建函式也是呼叫__getattr__
self._dict[item]本身就是訪問例項屬性
Corrent Sample:
d={
'b':22,
'bb':33
}
class Dict2Obj(object):
def __init__(self,d:dict):
# self.__dict__={'_dict':d} # 覆蓋例項建立時的字典,依然會呼叫__setattr__
if not isinstance(d,(dict,)):
self.__dict__['_dict']={}
else:
self.__dict__['_dict']=d
def __getattr__(self,item):
try:
return self._dict[item]
except KeyError:
raise AttributeError('Attribute {} not found!'.format(item))
def __setattr__(self,key,value):
raise NotImplementedError
b=Dict2Obj(d)
print(b.__dict__)
print(b.b,b.bb)
不允許動態增加屬性,通過__dict__依然可以增加,不提倡