描述
特性和描述符,管理属性时,实例属性用前单下划线开头,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
python内置操作和对应方法。
NO | 内置操作 | 对应方法 |
---|---|---|
1 | 索引操作[i] | __getitem__ |
2 | 加法(连接)操作+ | __coerce__ __add__ |
3 | 括号调用() | __call__ |
4 | 打印print() | __str__ |
__coerce__:表示强制类型转换,使用加法(或连接)操作+时,不同类型会触发类型转换或者报错。
用法
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
# 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)
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>
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>