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__依然可以增加,不提倡