• python运算符重载(二)


    一、基础知识

    定义:当类中提供了某个特殊名称的方法,在该类的实例出现在它们相关的表达式时,Python自动调用它们
    特性:
        1、运算符重载让类拦截常规的Python运算。
        2、类可重载所有Python表达式运算符。
        3、类可重载打印,函数调用,属性点号运算等内置运算
        4、重载使类实例的行为像内置类型
        5、重载是通过提供特殊名称的类方法来实现的
    

    二、字典索引和分片:_getitem_,_setitem_,_delitem_

    如果在类中定义了(或者继承了)的话,则对于实例中的索引运算,会自动调用__getitem__,__setitem__,__delitem__三个方法。当实例X出现X[i]这样的索引运算时,Python会调用这个实例继承的__getitem__,__setitem__,__delitem__方法(如果有的话)
    
    class Foo:
        def __init__(self,name):
            self.name=name
        def __getitem__(self, item):
            return self.__dict__[item]
        def __setitem__(self, key, value):
            self.__dict__[key]=value
        def __delitem__(self, key):
            del self.__dict__[key]
            
            
    F=Foo('egon')           #实例化
    print(F['name'])        #打印,以字典索引的方式,会找到__getitem__方法下的代码,‘name’传递给第二个参数
    F['age']=18             #赋值操作,直接传递给__setitem__方法
    print(F.__dict__)       #打印F的命名空间
    del F['age']            #del会调用__delitem__方法,删除‘age’
    print(F.__dict__)
    
    打印结果为:
    egon
    {'name': 'egon', 'age': 18}
    {'name': 'egon'}
    

    三、_slots_

    __slots__:实例化的对象将没有名称空间,都保存在类的名称空间,而且只能设置指定的属性,例如下面的例子,每个实例只能设置x,y,z三个属性
    
    class People:
        __slots__=['x','y','z'] 
    
    p=People
    p.x=1
    p.y=2
    p.z=3
    print(People.__dict__)
    p.e=4   #这个将会报错
    

    四、迭代器对象:_iter_,_next_

    python 中所有的迭代环境都会先尝试__iter__方法,再尝试__getitem__,也就是说,只有对象在不支持迭代的情况下,才会尝试索引的方式运算。
    Python中,迭代环境是通过调用内置函数iter去尝试寻找__iter__方法来实现的,而这种方法返回一个迭代器对象,如果已经提供了,Python就会重复调用这个迭代器对象的next方法,知道发生了StopIteration异常
    
    class Range:
        def __init__(self,start,end,long):   #构造函数,定义三个元素,start,end,long
            self.start=start
            self.end=end
            self.long=long
        def __iter__(self):                 #__iter__:生成迭代器对象self
            return self                     #返回这个迭代器本身
        def __next__(self):                 #__next__:一个一个返回迭代器内的值
            if self.start>=self.end:
                raise StopIteration
            n=self.start
            self.start+=self.long
            return n
    
    r=Range(1,10,2)    #实例化对象r,
    for i in r:        #r会首先调用__iter__方法,把自己转换为迭代器
        print(i)
    

    五、实现上下文管理:with/as,_enter_,_exit_

    with open('a.txt') as f:#with代码块后会自定关闭文件,无论是否发生异常,一下是with的工作方式:
        1、计算表达式,所得到的对象称为环境管理器,他必须有__enter__,__exit__方法。
        2、环境管理器的__enter__方法会被调用。如果as字句存在,器返回值会赋值给as字句中的变量,否则直接丢弃。
        3、代码块中嵌套的代码会执行。
        4、如果with代码块引发异常,__exit__(type,value,traceback)方法就会调用(带有异常细节)
        5、如果with代码块没有引发异常,__exit__方法依然会被调用,其type,value,traceback参数都会以none传递
    
    import time
    class Open:
        def __init__(self,filepath,mode='r',encoding='utf8'):
            self.filepath=filepath
            self.mode=mode
            self.encoding=encoding
            self.x=open(filepath,mode=mode,encoding=encoding)
    
        def write(self,line):
            t=time.strftime('%Y-%m-%d %X')
            self.x.write('%s %s' %(t,line))
        def __getattr__(self, item):
            return getattr(self.x,item)
    
        def __enter__(self):
            print("*************")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('文件关闭')
            self.x.close()
            
    with Open('a.txt','w') as f:  #出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
        f.write("abc")            #调用自己定义的write方法,把‘abc’ 写入到a.txt文件
        print('==============')   #这一行代码执行完毕后,会触发__exit__方法,关闭文件
    print("继续执行代码")
    
    #代码执行如下
    *************
    ==============
    文件关闭
    继续执行代码
    

    六、_call_:python会为实例用函数调用的表达式运行__call__方法,这样就可以让类实例的外观看起来像是函数

    class callee:
        def __call__(self, *args, **kwargs):
            print('call:',args,kwargs)
    C=callee()
    C(1,2,3)         #实例加()后,会调用__call__方法
    C(1,2,3,X=4,Y=5)
    
    #打印结果如下
    call: (1, 2, 3) {}
    call: (1, 2, 3) {'X': 4, 'Y': 5}
    

    七、_del_:析构函数

    每当实例产生时,就对调用__init__构造函数,没当实例空间被收回时,就会调用__del__析构函数。吃方法一般不需定义,python 有自己的内存回收机制
    
    import time
    class Open:
        def __init__(self,filepath,mode='r',encoding='utf8'):
            self.filepath=filepath
            self.mode=mode
            self.encoding=encoding
            self.x=open(filepath,mode=mode,encoding=encoding)
        def __del__(self):
            print('del')
            self.x.close()
    f=Open('a.txt','w')
    
    del f
    
  • 相关阅读:
    alpha冲刺1/4
    第二次作业
    第一次作业
    第一次个人作业
    第10组 Beta版本演示
    第10组 Beta冲刺(4/4)
    第10组 Beta冲刺(3/4)
    第10组 Beta冲刺(2/4)
    第10组 Beta冲刺(1/4)
    第10组 Alpha冲刺(4/4)
  • 原文地址:https://www.cnblogs.com/baomanji/p/6762592.html
Copyright © 2020-2023  润新知