python属性管理getattr、getattribute、setattr和delattr避免循环

发布时间:2024年01月06日

1 python属性管理getattr、getattribute、setattr和delattr避免循环

在__getattr__()、__getattribute__()和__setattr__()方法体内,通过self进行对应的点号运算、赋值运算,会自动调用当前实例的相应方法,导致无限循环。通过object或者__dict__可以避免循环。

NO项目方法体内避免循环
1__getattr__()已定义属性attr,self.attr
2__getattribute__()object.__getattribuite__(self,attr)
3__setattr__()object.__setattr__(self,attr,value) self.__dict__[attr]=value
4__delattr__()object.__delattr__(self,attr) del self.__dict__[attr]

1.1 getattr

未定义属性attr,进行点号运算-实例名.attr时,自动调用__getattr__()方法,所以可以在方法体对已定义属性进行点号运算,不会产生循环,因为实例名.已定义属性,不会触发__getattr__()方法。注意,方法体内不能对未定义属性进行点号运算,否则会产生循环。

1.1.1 self.attr触发无限循环

描述

getattr方法体内,未定义属性attr,self.attr,点号运算触发无限循环。

示例

>>> class LoopGet:
    a=1
    def __init__(self):
        self.b=2
    def __getattr__(self,attr):
        print('获取属性值',attr)
        # 未定义属性attr,self.attr,点号运算,触发循环
        x=self.attr

        
>>> lg=LoopGet()
>>> lg.a
1
>>> lg.c
获取属性值 c
获取属性值 attr
获取属性值 attr
获取属性值 attr
获取属性值 attr
# 未定义属性attr,实例名.attr,点号运算,触发循环

1.1.2 访问已定义属性避免循环

描述

__getattr__拦截未定义属性的点号运算,方法体内,self.已定义属性,拦截已定义属性来避免循环,或者直接return其他值来避免循环。

示例

>>> class LoopGet:
    a=1
    def __init__(self):
        self.b=2
    def __getattr__(self,attr):
        print('获取属性值',attr)
        # 已定义属性attr,self.attr,点号运算,不调用 __getattr__ , 避免循环
        x=self.a

        
>>> lg=LoopGet()
>>> lg.c
获取属性值 c

1.2 getattribute

未定义属性、已定义属性attr,进行点号运算-实例名.attr时,都会自动调用__getattribute__()方法,所以在方法体通过self.属性,对其他属性进行点号运算时,会触发__getattribute__(),导致产生循环。通过object.__getattribute__()避免无限循环。

1.2.1 self.attr触发无限循环

描述

getattribute方法体内,self.属性名,自动调用当前实例的getattribute,导致无限循环。

示例

>>> class LoopGet:
    a=1
    def __init__(self):
        self.b=2
    def __getattribute__(self,attr):
        print('获取属性值',attr)
        # 已定义属性attr,self.attr,点号运算,触发循环
        x=self.b
>>> lg=LoopGet()
>>> lg.a
获取属性值 a
获取属性值 b
获取属性值 b
获取属性值 b
#无限循环获取属性 b



>>> class LoopGet:
    a=1
    def __init__(self):
        self.b=2
    def __getattribute__(self,attr):
        print('获取属性值',attr)
        # 未定义属性attr,self.attr,点号运算,触发循环
        x=self.attr

        
>>> lg=LoopGet()
>>> lg.a
获取属性值 a
获取属性值 attr
获取属性值 attr
获取属性值 attr
#无限循环获取属性 attr

1.2.2 self.__dict__触发无限循环

描述

getattribute方法体内,self.__dict__,自动调用当前实例的getattribute,导致无限循环。

示例

>>> class LoopGet:
    a=1
    def __init__(self):
        self.b=2
    def __getattribute__(self,attr):
        print('获取属性值',attr)
        # self.__dict__ 触发 __getattribute__ ,导致循环
        x=self.__dict__[attr]

        
>>> lg=LoopGet()
>>> lg.a
获取属性值 a
获取属性值 __dict__
获取属性值 __dict__

1.2.3 object.getattribute()避免循环

描述

getattribute方法体内,object.__getattribute__(self,attr),自动调用超类object的getattribute,避免无限循环。

示例

>>> class LoopGet:
    a=1
    def __init__(self):
        self.b=2
    def __getattribute__(self,attr):
        print('获取属性值',attr)
        # object全部类的超类,通过 object.__getattribute__ 避免循环
        return object.__getattribute__(self,attr)

>>> lg=LoopGet()
>>> lg.a
获取属性值 a
1
>>> lg.c
获取属性值 c
Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    lg.c
  File "<pyshell#16>", line 8, in __getattribute__
    return object.__getattribute__(self,attr)
AttributeError: 'LoopGet' object has no attribute 'c'

1.3 setattr

未定义属性或已定义类属性或已定义实例属性为attr,实例名.attr=value,自动调用python的__setattr__()方法。在setattr方法体内,self.attr=value,自动调用当前实例的setattr,导致无限循环。通过self.__dict__[attr]=value、object.__setattr__(self,attr,value)来避免无限循环。

__delattr__()和__setattr__()使用相同的方法来避免循环。

1.3.1 self.attr=value触发无限循环

描述

setattr方法体内,self.attr=value,自动调用当前实例的setattr,导致无限循环。

示例

>>> class LoopGet:
    a=1
    def __init__(self):
        self.b=2
    def __setattr__(self,attr,value):
        print('设置属性值',attr)
        # self.attr 触发 __getattribute__ ,导致循环
        self.attr=value

# 构造函数的 self.b=2 调用 setattr,方法体内 self.attr=value ,触发无限循环        
>>> lg=LoopGet()
设置属性值 b
设置属性值 attr
设置属性值 attr
设置属性值 attr

1.3.2 self.dict[attr]=value避免循环

描述

__setattr__()方法体内,self.__dict__[attr]=value,不调用setattr,避免循环。

示例

>>> class LoopGet:
    a=1
    def __init__(self):
        self.b=2
    def __setattr__(self,attr,value):
        print('设置属性值',attr)
        # self.__dict__[attr]=value 不调用 __getattribute__ ,避免循环
        self.__dict__[attr]=value

        
>>> lg=LoopGet()
设置属性值 b
>>> lg.a=11
设置属性值 a
>>> lg.b=3
设置属性值 b
>>> lg.c=5
设置属性值 c
>>> lg.c
5

1.3.3 object.setattr(self,attr,value)避免循环

描述

__setattr__()方法体内,object.__setattr__(self,attr,value),自动调用超类object的setattr,避免无限循环。

示例

>>> class LoopGet:
    a=1
    def __init__(self):
        self.b=2
    def __setattr__(self,attr,value):
        print('设置属性值',attr)
        # object.__setattr__(self,attr,value) 调用超类setattr ,避免循环
        object.__setattr__(self,attr,value)

        
>>> lg=LoopGet()
设置属性值 b
>>> lg.a=11
设置属性值 a
>>> lg.b=3
设置属性值 b
>>> lg.c=5
设置属性值 c
>>> lg.c
5

1.4 delattr

del 实例名.attr,自动调用python的__delattr__()方法。在setattr方法体内,del self.attr自动调用当前实例的delattr,导致无限循环。

通过del self.__dict__[attr]、object.__delattr__(self,attr)来避免无限循环。

注:只能删实例属性,不能删类属性。

1.4.1 del self.attr触发无限循环

描述

__delattr__()方法体内,del self.attr,自动调用当前实例的delattr,导致无限循环。

示例

>>> class LoopDel:
    a=1
    def __init__(self):
        self.b=2
    def __delattr__(self,attr):
        print('删除属性',attr)
        # del self.attr ,调用当前实例的 delattr , 导致循环
        del self.attr

        
>>> ld=LoopDel()
>>> del ld.a
删除属性 a
删除属性 attr
删除属性 attr
删除属性 attr
删除属性 attr

1.4.2 del self.dict[attr]避免循环

描述

__delattr__()方法体内,del self.__dict__[attr],不调用delattr,避免循环。

注:只能删实例属性,不能删类属性。

示例

>>> class LoopDel:
    a=1
    def __init__(self):
        self.b=2
    def __delattr__(self,attr):
        print('删除属性',attr)
        # del self.__dict__[attr] ,不调用 delattr , 避免循环
        # 只能删 实例属性, 不能删类属性
        del self.__dict__[attr]

>>> ld=LoopDel()
# 删实例属性
>>> del ld.b
删除属性 b
# 删类属性失败
>>> del ld.a
删除属性 a
Traceback (most recent call last):
  File "<pyshell#64>", line 1, in <module>
    del ld.a
  File "<pyshell#60>", line 9, in __delattr__
    del self.__dict__[attr]
KeyError: 'a'

1.4.3 object.__delattr(self,attr)避免循环

描述

__delattr__()方法体内,object.__delattr__(self,attr),自动调用超类object的delattr,避免无限循环。

注:只能删实例属性,不能删类属性。

示例

>>> class LoopDel:
    a=1
    def __init__(self):
        self.b=2
    def __delattr__(self,attr):
        print('删除属性',attr)
        # object.__delattr__(self,attr) ,调用超类 delattr , 避免循环
        # 只能删 实例属性, 不能删类属性
        object.__delattr__(self,attr)

        
>>> ld=LoopDel()
>>> del ld.b
删除属性 b
>>> del ld.a
删除属性 a
Traceback (most recent call last):
  File "<pyshell#69>", line 1, in <module>
    del ld.a
  File "<pyshell#66>", line 8, in __delattr__
    object.__delattr__(self,attr)
AttributeError: a
文章来源:https://blog.csdn.net/sinat_34735632/article/details/135433313
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。