python运算符重载之成员关系和属性运算

1 python运算符重载之成员关系和属性运算

1.1 重载成员关系运算符

1.1.1 contains,iter,getitem

python使用成员关系运算符in时,

按优先级调用方法:contains>iter>getitem

class MyIters:
    def __init__(self,value):
        self.data=value
    def __getitem__(self,i):
        print('get[{}]:'.format(i),end='')
        return self.data[i]
    #def __iter__(self):
    #   print('iter=> ',end='')
    #   self.ix=0
    #   return self
    #def __next__(self):
    #   print('next:',end='')
    #   if self.ix==len(self.data):
    #       raise StopIteration
    #   item=self.data[self.ix]
    #   self.ix+=1
    #   return item
    #def __contains__(self,x):
    #   print('contains: ',end='')
    #   return x in self.data

if __name__ == '__main__':
    mi=MyIters('tyxt')
    print('t' in mi)# in 按 contains > iter> getitem顺序调用
    for i in mi:# for 调用 iter 和 next 、 getitem
        print(i,end=' | ')
    print()
    print([i*2 for i in mi])
    print(list(map(ord,mi)))
    i=iter(mi)
    while True:
        try:
            print(next(i),end='#')
        except StopIteration:
            break
''' #未注释contains,按contains>iter>getitem顺序调用
E:\documents\F盘>python myIn.py
contains: True
iter=> next:t | next:y | next:x | next:t | next:
iter=> next:next:next:next:next:['tt', 'yy', 'xx', 'tt']
iter=> next:next:next:next:next:[116, 121, 120, 116]
iter=> next:t#next:y#next:x#next:t#next:
E:\documents\F盘>
'''
''' #注释contains,按contains>iter>getitem顺序调用
E:\documents\F盘>python myIn.py
iter=> next:True
iter=> next:t | next:y | next:x | next:t | next:
iter=> next:next:next:next:next:['tt', 'yy', 'xx', 'tt']
iter=> next:next:next:next:next:[116, 121, 120, 116]
iter=> next:t#next:y#next:x#next:t#next:
'''
''' #注释contains 和 iter ,按contains>iter>getitem顺序调用
E:\documents\F盘>python myIn.py
get[0]:True
get[0]:t | get[1]:y | get[2]:x | get[3]:t | get[4]:
get[0]:get[1]:get[2]:get[3]:get[4]:['tt', 'yy', 'xx', 'tt']
get[0]:get[1]:get[2]:get[3]:get[4]:[116, 121, 120, 116]
get[0]:t#get[1]:y#get[2]:x#get[3]:t#get[4]:
'''

1.2 重载属性运算符

1.2.1 getattr

python的__getattr__方法,拦截不存在的或未定义的属性点号运算。

>>> class MyGet:
    # 通过点号运算访问不存在的属性时自动调用getattr
    def __getattr__(self,attr):
        if attr=='name':
            return '梯阅线条'
        else:
            raise AttributeError(attr)
>>> mg=MyGet()
>>> mg.name
'梯阅线条'
>>> mg.age
Traceback (most recent call last):
  File "", line 1, in <module>
    mg.age
  File "", line 6, in __getattr__
    raise AttributeError(attr)
AttributeError: age
# 存在的属性不会调用getattr
>>> mg.addr='深圳'
>>> mg.addr
'深圳'

1.2.2 setattr

python的__setattr__方法,会拦截全部的属性赋值语句。

实现__setattr__方法时,必须通过属性字典进行赋值,

如果通过点号赋值,会自动调用__setattr__方法,进入无限循环,导致堆栈溢出程序异常。

>>> class MySet:
    # 通过点号运算给属性赋值时自动调用 setattr 方法
    def __setattr__(self,attr,value):
        if attr=='name':
            # 必须通过字典属性赋值方式实现
            self.__dict__[attr]=value
        else:
            raise AttributeError(attr+' 禁止设置')
>>> ms=MySet()
>>> ms.name='梯阅线条'
>>> ms.name
'梯阅线条'
>>> ms.age=9555
Traceback (most recent call last):
  File "", line 1, in <module>
    ms.age=9555
  File "", line 6, in __setattr__
    raise AttributeError(attr+' 禁止设置')
AttributeError: age 禁止设置

1.2.3 私有属性列表

通过setattr拦截属性赋值,如果在私有属性列表里面,禁止赋值。

>>> class MyPrivateExc(Exception):pass
>>> class MyPrivacy:
    def __setattr__(self,attr,value):
        # 私有变量名列表,禁止赋值操作
        if attr in self.privates:
            raise MyPrivateExc(attr,self)
        else:
            self.__dict__[attr]=value       
>>> class MyTest1(MyPrivacy):
    privates=['age']    
>>> class MyTest2(MyPrivacy):
    privates=['name','pay']
    def __init__(self):
        self.__dict__['name']='梯阅线条'
>>> mt1=MyTest1()
>>> mt2=MyTest2()
>>> mt1.name='张三'
>>> mt2.name='李四'
Traceback (most recent call last):
  File "", line 1, in <module>
    mt2.name='李四'
  File "", line 4, in __setattr__
    raise MyPrivateExc(attr,self)
MyPrivateExc: ('name', <__main__.MyTest2 object at 0x00E3F650>)
>>> mt1.age=9555
Traceback (most recent call last):
  File "", line 1, in <module>
    mt1.age=9555
  File "", line 4, in __setattr__
    raise MyPrivateExc(attr,self)
MyPrivateExc: ('age', <__main__.MyTest1 object at 0x00E3F630>)
>>> mt2.age=9555
>>> mt2.age
9555
>>> mt2.name
'梯阅线条'

你可能感兴趣的:(python,python)