专业编程基础技术教程

网站首页 > 基础教程 正文

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

ccvgpt 2024-08-05 12:12:29 基础教程 11 ℃

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

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

NO

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

项目

方法体内避免循环

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


本文首发微信公众号:梯阅线条

更多内容参考python知识分享或软件测试开发目录。

Tags:

最近发表
标签列表