专业编程基础技术教程

网站首页 > 基础教程 正文

python的getattr和getattribute调用

ccvgpt 2024-08-05 12:12:26 基础教程 45 ℃

1 python的getattr和getattribute调用

python类的属性包括类属性、实例属性,

类属性:直接在类顶层赋值,或通过类名.属性名=值赋值;

python的getattr和getattribute调用

实例属性:通过self赋值,或通过实例名.属性名=值赋值;

类实例可以访问类属性和实例属性;


python的特性和描述符都用于管理属性。

一个特性或描述符管理一个单个的、特定的属性。

getattr、getattribute、setattr、delattr 可以管理多个属性。

重载__getattr__()和__getattribute__()方法,在获取类实例属性值时会被自动调用。

(1)__getattr__(),针对实例属性,获取属性值时,会被自动调用;

(2)__getattribute__(),针对类和实例属性,获取属性值时,会被自动调用。

用于基于委托的场景,比如,包装对象,管理嵌套对象的全部属性访问。

用法

 class C:
     def __getattr__(self,name):pass
     def __getattribute__(self,name):pass
     def __setattr__(self,name,value):pass
     def __delattr__(self,name):pass
 c=C()

描述

类实例c,

未定义属性attr,c.attr自动调用__getattr__(),

未定义或已定义属性attr,c.attr自动调用__getattribute__(),

设置实例属性值时,c.attr=value,自动调用__setattr__(),

删除实例属性时,del c.attr,自动调用__delattr__()。

__getattr__()和__getattribute__()需返回一个值。

未定义属性attr,同时存在__getattr__()和__getattribute__(),c.attr自动调用getattribute,不调用getattr。

都是通过实例名操作属性时自动调用对应方法,通过类名操作属性不触发对应方法的调用。

1.1 getattr

描述

python的__getattr__()方法,针对未定义的属性,拦截属性点号运算,即未定义的属性进行点号运算(.属性名)时自动调用getattr方法。已定义的属性进行点号运算不调用getattr方法。

类名不可访问实例属性,所以,通过类名操作实例属性报错。

未定义属性attr,实例名.attr,自动调用getattr。

NO

点号运算

是否调用getattr

1

未定义属性attr,实例名.attr

自动调用

2

未定义属性attr,类名.attr

不调用,报错 AttributeError

3

已定义类属性attr,实例名.attr

不调用

4

已定义实例属性attr,实例名.attr

不调用

5

已定义类属性attr,类名.attr

不调用

6

已定义实例属性attr,类名.attr

不调用,报错 AttributeError


示例

 >>> class MyGet:
     day=30
     def __init__(self):
         self.url='www.tyxt.work'
     # 未定义的属性进行点号运算,自动调用 __getattr__
     def __getattr__(self,attr):
         print('__getattr__拦截点号运算')
         if attr=='name':
             return '梯阅线条'
         else:
             raise AttributeError(attr)
 
         
 >>> mg=MyGet()
 # 已定义的类属性和实例属性,实例名.属性,不调用 __getattr__
 >>> mg.day,mg.url
 (30, 'www.tyxt.work')
 >>> mg.addr='深圳'
 >>> mg.addr
 '深圳'
 # 未定义的属性,实例名.属性,自动调用 __getattr__
 >>> mg.name
 __getattr__拦截点号运算
 '梯阅线条'
 >>> mg.age
 __getattr__拦截点号运算
 Traceback (most recent call last):
   File "<pyshell#20>", line 1, in <module>
     mg.age
   File "<pyshell#16>", line 11, in __getattr__
     raise AttributeError(attr)
 AttributeError: age
 # 已定义的类属性,类名.属性,不调用 __getattr__
 >>> MyGet.day
 30
 # 未定义的属性,类名.属性,不调用 __getattr__ ,报错
 >>> MyGet.month
 Traceback (most recent call last):
   File "<pyshell#85>", line 1, in <module>
     MyGet.month
 AttributeError: type object 'MyGet' has no attribute 'month'
 # 已定义的实例属性,类名.实例属性,不调用 __getattr__ ,报错
 >>> MyGet.url
 Traceback (most recent call last):
   File "<pyshell#94>", line 1, in <module>
     MyGet.url
 AttributeError: type object 'MyGet' has no attribute 'url'

1.2 getattribute

描述

python的__getattribute__()方法,针对全部属性,拦截属性点号运算,即全部属性的点号运算(.属性名),自动调用getattribute方法,包括已定义和未定义的属性。

实例可访问类属性和实例属性,所以,包括类属性和实例属性的点号运算。

类名不可访问实例属性,所以,通过类名操作实例属性报错。

未定义属性或已定义类属性或已定义实例属性为attr,实例名.attr,自动调用getattribute。

NO

点号运算

是否调用getattribute

1

未定义属性attr,实例名.attr

自动调用

2

未定义属性attr,类名.attr

不调用,报错 AttributeError

3

已定义类属性attr,实例名.attr

自动调用

4

已定义实例属性attr,实例名.attr

自动调用

5

已定义类属性attr,类名.attr

不调用

6

已定义实例属性attr,类名.attr

不调用,报错 AttributeError


示例

 >>> class MyGet:
     day=30
     def __init__(self):
         self.url='www.tyxt.work'
     # 全部属性的点号运算,自动调用 __getattribute__
     def __getattribute__(self,attr):
         print('__getattribute__ 拦截全部属性的点号运算,包括已定义和未定义的属性',attr)
 
         
 >>> mg=MyGet()
 # 已定义的类属性和实例属性,实例名.属性,自动调用 __getattribute__
 >>> mg.day,mg.url
 __getattribute__ 拦截全部属性的点号运算,包括已定义和未定义的属性 day
 __getattribute__ 拦截全部属性的点号运算,包括已定义和未定义的属性 url
 (None, None)
 >>> mg.addr='深圳'
 >>> mg.addr
 __getattribute__ 拦截全部属性的点号运算,包括已定义和未定义的属性 addr
 # 已定义的类属性,类名.类属性,不调用 __getattribute__
 >>> MyGet.day
 30
 # 已定义的实例属性,类名.实例属性,不调用 __getattribute__ ,报错 
 >>> MyGet.url
 Traceback (most recent call last):
   File "<pyshell#91>", line 1, in <module>
     MyGet.url
 AttributeError: type object 'MyGet' has no attribute 'url'
 # 未定义的属性,实例名.属性,自动调用 __getattribute__
 >>> mg.name
 __getattribute__ 拦截全部属性的点号运算,包括已定义和未定义的属性 name
 # 未定义的属性,类名.属性,不调用 __getattribute__ , 报错
 >>> MyGet.name
 Traceback (most recent call last):
   File "<pyshell#89>", line 1, in <module>
     MyGet.name
 AttributeError: type object 'MyGet' has no attribute 'name'

1.3 setattr

描述

python的__setattr\()方法,超类和本类的self.attr=value赋值运算、实例名.attr=value赋值运算、原属性修改和新属性设置的赋值运算,都会自动调用 setattr方法。

类名.attr=value赋值运算,不调用settattr方法。

实例可访问类属性和实例属性,所以,包括类属性和实例属性的赋值运算。

未定义属性或已定义类属性或已定义实例属性为attr,实例名.attr=value,自动调用setattr。


NO

赋值运算

是否调用setattr

1

超类self.attr=value

自动调用

2

本类self.attr=value

自动调用

3

已定义实例属性attr,实例名.attr=value,超类和本类

自动调用

4

已定义类属性attr,实例名.attr=value,超类和本类

自动调用

5

未定义属性attr,实例名.attr=value

自动调用

6

已定义实例属性attr,类名.attr=value,超类和本类

不调用

7

已定义类属性attr,类名.attr=value,超类和本类

不调用

8

未定义属性attr,类名.attr=value,超类和本类

不调用


示例

 >>> class MySuper:
     x=1
     def __init__(self,addr):
         self.addr=addr
         self.tel=110
         
 >>> class MySet(MySuper):
     day=30
     def __init__(self):
         self.url='www.tyxt.work'
         super().__init__('深圳')
     # 全部实例属性的赋值运算,自动调用 __setattr__
     # 包括超类属性的赋值运算
     # 包括原属性修改和新属性设置的赋值运算
     # 不包括类属性的赋值运算
     # 实例属性赋值形式:self.attr=value,实例名.attr=value
     def __setattr__(self,attr,value):
         print('__setattr__ 拦截实例属性的赋值运算,包括超类实例属性',attr)
 
 # 超类和本类的self.attr=value赋值运算,自动调用 __setattr__ 
 # 类原属性赋值(x=1和day=30)运算,不调用 __setattr__
 >>> ms=MySet()
 __setattr__ 拦截实例属性的赋值运算,包括超类实例属性 url
 __setattr__ 拦截实例属性的赋值运算,包括超类实例属性 addr
 __setattr__ 拦截实例属性的赋值运算,包括超类实例属性 tel
 # 实例名.attr=value,原实例属性赋值运算,自动调用 __setattr__ 
 >>> ms.tel=120
 __setattr__ 拦截实例属性的赋值运算,包括超类实例属性 tel
 >>> ms.url='tyxt.work'
 __setattr__ 拦截实例属性的赋值运算,包括超类实例属性 url
 # 实例名.attr=value,新属性赋值运算,自动调用 __setattr__ 
 >>> ms.age=9555
 __setattr__ 拦截实例属性的赋值运算,包括超类实例属性 age
 # 实例名.attr=value,原类属性赋值运算,自动调用 __setattr__ 
 >>> ms.x=2;ms.day=31
 __setattr__ 拦截实例属性的赋值运算,包括超类实例属性 x
 __setattr__ 拦截实例属性的赋值运算,包括超类实例属性 day
 # 类新属性赋值运算,不调用 __setattr__
 >>> MySuper.y=2
 >>> MySet.month=12

1.4 delattr

描述

python的__delattr__()方法,del 实例名.属性,删除类属性和实例属性、未定义的属性,都会自动调用 delattr方法。

实例可访问类属性和实例属性,所以,包括类属性和实例属性的删除操作。

类名不可访问实例属性,所以,通过类名操作实例属性报错。

未定义属性或已定义类属性或已定义实例属性为attr,del 实例名.attr,自动调用delattr。


NO

删除操作

是否调用delattr

1

已定义实例属性attr,del 实例名.attr

自动调用

2

已定义类属性attr,del 实例名.attr

自动调用

3

未定义属性attr,del 实例名.attr

自动调用

4

已定义实例属性attr,del 类名.attr

不调用,报错 AttributeError

5

已定义类属性attr,del 类名.attr

不调用

6

未定义属性attr,del 类名.attr

不调用,报错 AttributeError

示例

 >>> class MyDel:
     day=30
     def __init__(self):
         self.url='www.tyxt.work'
     # del 实例名.属性,自动调用 __delattr__
     def __delattr__(self,attr):
         print('__delattr__ 拦截 del 实例名.属性 运算',attr)
 
         
 >>> md=MyDel()
 # del 实例名.类属性,自动调用 __delattr__
 >>> del md.day
 __delattr__ 拦截 del 实例名.属性 运算 day
 # del 实例名.实例属性,自动调用 __delattr__
 >>> del md.url
 __delattr__ 拦截 del 实例名.属性 运算 url
 # del 类名.类属性,不调用 __delattr__
 >>> del MyDel.day
 # del 类名.实例属性,不调用 __delattr__ , 报错
 >>> del MyDel.url
 Traceback (most recent call last):
   File "<pyshell#105>", line 1, in <module>
     del MyDel.url
 AttributeError: url
 # del 实例名.attr ,attr 为不存在的属性 , 自动调用 __delattr__
 >>> del md.x
 __delattr__ 拦截 del 实例名.属性 运算 x

1.5 getattr和getattribute同时存在

描述

同时定义__getattr__()和__getattribute__()两个方法,未定义属性attr,实例名.attr,只调用getattribute方法,不调用getattr方法。

示例

 >>> class MyGet:
     day=30
     def __init__(self):
         self.url='www.tyxt.work'
     # 未定义的属性进行点号运算,自动调用 __getattr__
     def __getattr__(self,attr):
         print('__getattr__拦截点号运算')
     # 全部属性的点号运算,自动调用 __getattribute__
     def __getattribute__(self,attr):
         print('__getattribute__ 拦截全部属性的点号运算,包括已定义和未定义的属性',attr)
 
 >>> mg=MyGet()
 # 已定义类属性 day , 实例名.day , 自动调用 __getattribute__
 >>> mg.day
 __getattribute__ 拦截全部属性的点号运算,包括已定义和未定义的属性 day
 # 已定义实例属性 url , 实例名.url , 自动调用 __getattribute__
 >>> mg.url
 __getattribute__ 拦截全部属性的点号运算,包括已定义和未定义的属性 url
 # 未定义属性 x , 实例名.x , 自动调用 __getattribute__
 >>> mg.x
 __getattribute__ 拦截全部属性的点号运算,包括已定义和未定义的属性 x


2 END

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

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

Tags:

最近发表
标签列表