专业编程基础技术教程

网站首页 > 基础教程 正文

python的getattr和getattribute拦截内置操作

ccvgpt 2024-08-05 12:12:30 基础教程 13 ℃

1 python的getattr和getattribute拦截内置操作

1.1 特性描述符getattr(bute)管理属性比较

描述

特性和描述符,管理属性时,实例属性用前单下划线开头,self._attr。

python的getattr和getattribute拦截内置操作

__getattr__(),管理属性时,未定义属性的点号运算返回已定义属性的点号运算。

__getattribute__(),管理属性时,用object.__getattribute__(self,name,value),避免循环。

示例

 
 
 >>> class SquareCubePro:
     '''
         property 特性计算平方和立方
         前下化线开头属性名存储基础数据
         赋值为特性的属性名不带下划线
         self._square和square=property:
         实例属性和特性属性不能同名,避免循环
     '''
     def __init__(self,sq,cu):
         self._square=sq
         self._cube=cu
     def getSquare(self):
         return self._square**2
     def setSquare(self,value):
         self._square=value
     square=property(getSquare,setSquare)
     
     def getCube(self):
         return self._cube**3
     cube=property(getCube)
 
     
 >>> scp=SquareCubePro(2,3)
 >>> scp.square,scp.cube
 (4, 27)
 >>> scp=SquareCubePro(3,5)
 >>> scp.square,scp.cube
 (9, 125)
 >>> scp.square=5
 >>> scp.square
 25
 
 
 
 >>> class SquareDesc:
     '''
         Descriptor 描述符计算平方和立方
         基础数据存储在客户类实例的属性上
     '''
     def __get__(self,instance,owner):
         return instance._square**2
     def __set__(self,instance,value):
         instance._square=value
 
         
 >>> class CubeDesc:
     def __get__(self,instance,owner):
         return instance._cube**3
 
     
 >>> class SquareCubeDesc:
     sq=SquareDesc()
     cu=CubeDesc()
     def __init__(self,sq,cu):
         self._square=sq
         self._cube=cu
 
         
 >>> scd=SquareCubeDesc(3,5)
 >>> scd.sq,scd.cu
 (9, 125)
 >>> scd.sq=5
 >>> scd.sq
 25
 
 >>> class SquareCubeGetA:
     '''
         重载 __getattr__ 计算平方和立方
     '''
     def __init__(self,sq,cu):
         self._square=sq
         self._cube=cu
     def __getattr__(self,name):
         if name=='square':
             return self._square**2
         elif name=='cube':
             return self._cube**3
         else:
             raise TypeError('属性错误:',name)
     def __setattr__(self,name,value):
         if name=='square':
             self.__dict__['_square']=value
         else:
             self.__dict__[name]=value
 
             
 >>> scga=SquareCubeGetA(3,5)
 >>> scga.square,scga.cube
 (9, 125)
 >>> scga.square=5
 >>> scga.square
 25
 
 >>> class SquareCubeGetAB:
     '''
         重载 __getattribute__ 计算平方和立方
     '''
     def __init__(self,sq,cu):
         self._square=sq
         self._cube=cu
     def __getattribute__(self,name):
         if name=='square':
             return object.__getattribute__(self,'_square')**2
         elif name=='cube':
             return object.__getattribute__(self,'_cube')**3
         else:
             return object.__getattribute__(self,name)
     def __setattr__(self,name,value):
         if name=='square':
             self.__dict__['_square']=value
         else:
             self.__dict__[name]=value
 
             
 >>> scgab=SquareCubeGetAB(3,5)
 >>> scgab.square,scgab.cube
 (9, 125)
 >>> scgab.square=5
 >>> scgab.square
 25

1.2 getattr和getattribute拦截内置操作


python内置操作和对应方法。

NO

内置操作

对应方法

1

索引操作[i]

__getitem__

2

加法(连接)操作+

__coerce__ __add__

3

括号调用()

__call__

4

打印print()

__str__

__coerce__:表示强制类型转换,使用加法(或连接)操作+时,不同类型会触发类型转换或者报错。


1.2.1 S.center(width[, fillchar]) -> string

用法

 S.center(width[, fillchar]) -> string

描述

python的s.center()使字符串居中对齐。

S:字符串;

width:字符串宽度;

fillchar:填充字符,字符串长度小于width时生效,否则不生效。

示例

 >>> strL=['MyGetAttr','MyGetAttribute']
 >>> for s in strL:
     print('\n'+s.center(50,'='))
     print('test center')
 
 ====================MyGetAttr=====================
 test center
 
 ==================MyGetAttribute==================
 test center

1.2.2 testgetattr.py

 # encoding:utf-8
 
 class MyGetAttr:
     name='梯阅线条'
     def __init__(self):
         self.url='tyxt.work'
     def __len__(self):
         print('__len__:9555')
         return 9555
     def __getattr__(self,attr):
         print('__getattr__:'+attr)
         if attr == '__str__':
             return lambda *args:'[GetAttr str]'
         else:
             return lambda *args:None
 
         
 class MyGetAttribute(object):
     name='梯阅线条'
     def __init__(self):
         self.url='tyxt.work'
     def __len__(self):
         print('__len__:9555')
         return 9555
     def __getattribute__(self,attr):
         print('__getattribute__:'+attr)
         if attr == '__str__':
             return lambda *args:'[Getattribute str]'
         else:
             return lambda *args:None
 
 if __name__=='__main__':     
     import sys
     print('python '+sys.version.split()[0])
     for C in MyGetAttr,MyGetAttribute:
         print('\n'+C.__name__.center(50,'='))
         c1=C()
         c1.name
         c1.url
         c1.tel
         len(c1)
         try:
             c1[0]
         except:
             print('fail []')
         try:
             c1+99
         except:
             print('fail +')
         try:
             c1()
         except:
             print('fail ()')
         c1.__call__()
         print(c1.__str__())
         print(c1)

1.2.3 python2.x的getattr和getattribute拦截内置操作

python2.x的__getattr__()拦截未定义属性操作,包括当前类内未定义的seq[i]、+、()、print()等内置操作。

python2.x的__getattribute__()拦截全部属性的点号运算、赋值运算、删除属性,不拦截当前类内未定义的seq[i]、+、()、print()等内置操作。

NO

调用方式

是否被__getattr__()拦截

是否被__ getattribute __()拦截

1

print(实例名)

被拦截

不被拦截

2

实例名.__str__()

被拦截

被拦截

3

实例名()

被拦截

不被拦截

4

实例名.__call__()

被拦截

被拦截

5

[]、+

被拦截

不被拦截


在cmd执行结果如下:

 C:\Users\Administrator>D:\Python27\python.exe E:\documents\F盘\testgetattr.py
 python 2.7.18
 
 ====================MyGetAttr=====================
 __getattr__:tel
 __len__:9555
 __getattr__:__getitem__
 __getattr__:__coerce__
 __getattr__:__add__
 __getattr__:__call__
 __getattr__:__call__
 __getattr__:__str__
 [GetAttr str]
 __getattr__:__str__
 [GetAttr str]
 
 ==================MyGetAttribute==================
 __getattribute__:name
 __getattribute__:url
 __getattribute__:tel
 __len__:9555
 fail []
 fail +
 fail ()
 __getattribute__:__call__
 __getattribute__:__str__
 [Getattribute str]
 <__main__.MyGetAttribute object at 0x00000000034B7C88>

1.2.4 python3.x的getattr和getattribute拦截内置操作

python3.x的__getattr__()拦截未定义属性操作,不拦截当前类内未定义的seq[i]、+、()、print()等内置操作。

python3.x的__getattribute__()拦截全部属性的点号运算、赋值运算、删除属性,不拦截当前类内未定义的seq[i]、+、()、print()等内置操作。

python3.x中,MyGetAttr未定义__str__(),但都未被__getattr__()拦截,因为从object继承了__str__()方法,所以不会被拦截。通过hasattr(MyGetAttr,'__str__')返回True验证。

python3.x中,MyGetAttribute未定义__str__(),通过print()打印不会被拦截,显式调用会被拦截。

python3.x中,调用小括号(),即__call__,不会被__getattr__()和__getattribute__()拦截,显式调用会被拦截。


NO

调用方式

是否被__getattr__()拦截

是否被__ getattribute __()拦截

1

print(实例名)

不被拦截

不被拦截

2

实例名.__str__()

不被拦截

被拦截

3

实例名()

不被拦截

不被拦截

4

实例名.__call__()

被拦截

被拦截

5

[]、+

不被拦截

不被拦截


在cmd执行结果如下:

 C:\Users\Administrator>D:\Python3\python.exe E:\documents\F盘\testgetattr.py
 python 3.7.8
 
 ====================MyGetAttr=====================
 __getattr__:tel
 __len__:9555
 fail []
 fail +
 fail ()
 __getattr__:__call__
 <__main__.MyGetAttr object at 0x01648E10>
 <__main__.MyGetAttr object at 0x01648E10>
 
 ==================MyGetAttribute==================
 __getattribute__:name
 __getattribute__:url
 __getattribute__:tel
 __len__:9555
 fail []
 fail +
 fail ()
 __getattribute__:__call__
 __getattribute__:__str__
 [Getattribute str]
 <__main__.MyGetAttribute object at 0x01648F50>

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

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

Tags:

最近发表
标签列表