字典属性化访问Dict2Obj & __setattr__的思考

 

 

 

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

  

字典属性化访问Dict2Obj & __setattr__的思考

 

 

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)

字典属性化访问Dict2Obj & __setattr__的思考

 

 

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



上一篇:Python:setattr 和 delatrr 方法


下一篇:Codeforces Round #633 (Div. 2) D. Edge Weight Assignment