python的getattr和getattribute拦截内置操作实现
作者:梯阅线条
1.1 特性描述符getattr(bute)管理属性比较
描述
特性和描述符,管理属性时,实例属性用前单下划线开头,self._attr。
__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的getattr和getattribute拦截内置操作实现的文章就介绍到这了,更多相关python的getattr和getattribute拦截内置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!