(董付国)Python 学习笔记---Python面向对象程序设计(3)

6.4.2 案例精选

  • 例6-1:自定义数组。在MyArray.py文件中,定义了一个数组类,重写了一部分特殊方法以支持数组之间、数组与整数之间的四则运算以及内积、大小比较、成员测试和元素访问等运算符。
class MyArray:                                              # 在内部封装/隐藏了一个列表
    '''All the elements in this array must be numbers'''

    def __IsNumber(self,n):                                 #定义了一个私有的成员方法
        return isinstance(n,(int,float,complex))

    def __init__(self,*args):                               #类的构造方法,‘*’可变长度参数
        if not args:
            self.__value = []                               #如果传值不是int,float,complex则给个空列表包装成数组
        else:
            for arg in args:
                if not self.__IsNumber(arg):
                    print('All elements must be numbers')
                    return
                self.__value = list(args)

    #重载运算符+
    #数组中每个元素都与数字n相加,或两个数组相加,返回新数组
    def __add__(self,n):
        if self.__IsNumber(n):
            #数组中所有元素都与数字n相加
            b = MyArray()                                   #构建一个空数组
            b.__value = [item+n for item in self.__value]   #列表推导式
            return b
        elif isinstance(n,MyArray):                         #MyArray是一个数组类型
            if len(n.__value) == len(self.__value):
                c = MyArray()
                c.__value = [i+j for i,j in zip(self.__value,n.__value)]
                return c
            else:
                print('Length not equal')
        else:
            print('Not supported')

    #重载运算符-
    #数组中每个元素都与数字n相减,返回新数组
    def __sub__(self,n):
        if not self.__IsNumber(n):
            #减法对于n的类型和数字类型之间不支持操作
            print('- operating with ',type(n),'and number type is not supported.')
            return
        b = MyArray()
        b.__value = [item-n for item in self.__value]
        return b

    #重载运算符*
    #数组中每个元素都与数字n相乘,返回新数组
    def __mul__(self,n):
        if not self.__IsNumber(n):
            #乘法对于n的类型和数字类型之间不支持操作
            print('* operating with ',type(n),'and number type is not supported.')
            return
        b = MyArray()
        b.__value = [item*n for item in self.__value]
        return b
    
    #重载运算符/
    #数组中每个元素都数字n相除,返回新数组
    def __truediv__(self,n):
        if not self.__value(n):
            #除法对于n的类型和数字不支持操作
            print(r'/ operating with',type(n),'and number is not supported.')
            return
        b = MyArray()
        b.__value = [item/n for item in self.__value]
        return b

    #重载运算符//
    #数组中每个元素都与数字n整除,返回新数组
    def __floordiv__(self,n):
        if not isinstance(n,int):
            print(n,' in not an integer')
            return
        b = MyArray()
        b.__value = [item//n for item in self.__value]

    #重载运算符%
    #数组中每个元素都数字n求余数,返回新数组
    def __mod__(self,n):
        if not self.__value(n):
            print(r'% operating with',type(n),'and number type is not supported.')
            return
        b = MyArray()
        b.__value = [item%n for item in self.__value]
        return b

    #重载运算符**
    #数组中每个元素都数字n求幂运算,返回新数组
    def __pow__(self,n):
        if not self.__value(n):
            print(r'** operating with',type(n),'and number type is not supported.')
            return
        b = MyArray()
        b.__value = [item**n for item in self.__value]
        return b

    def __len__(self):
        return len(self.__value)

    #直接使用该对象作为表达式来查看对象的值
    def __repr__(self):
        return repr(self.__value)

    #支持使用print()查看对象的值
    def __str(self):
        return str(self.__value)

    #追加元素
    def append(self,v):
        assert self.__IsNumber(v),'Only number can be appended.'        #如果v满足条件则返回数组,否则抛出异常

    #获取指定下标的元素值,支持使用列表或元组指定多个下标
    def __getitem__(self,index):
        length = len(self.__value)
        #如果指定单个整数作为下标,直接返回元素值
        if isinstance(index,int) and 0<=index<=length:
            return self.__value[index]
        elif isinstance(index,(list,tuple)):
            for i in index:
                if not (isinstance(i,int) and 0<=i<=length):
                    return 'index error'
            result = []
            for item in index:
                result.append(self.__value[item])
            return result
        else:
            return 'index error'

    #修改元素值,支持使用列表或元组指定多个下标,同时修改多个元素值
    def __setitem__(self,index,value):
        length = len(self.__value)
        #如果下标合法,则直接修改元素
        if isinstance(index,int) and 0<=index<=length:
            self.__value[index] = value
        #支持使用列表或元组指定多个下标
        elif isinstance(index,(list,tuple)):
            for i in index:
                if not isinstance((i,int) and 0<=i<=length):
                    raise Exception('index error')
                #如果下标和给的值都是元组或列表,并且个数一样,则分别为多个下标的元素修改值
                if isinstance(value,(list,tuple)):
                    if len(index) == len(value):
                        for i,v in enumerate(index):
                            self.__value[v] = value[i]
                    else:
                        raise Exception('value and index must be of the same length')
                #如果指定多个下标和一个普通值,则把多个元素修改为相同的值
                elif isinstance(value,(int,float,complex)):
                    for i in index:
                        self.__value[i] = value
                else:
                    raise Exception('value error')
        else:
            raise Exception('index error')

    #支持成员测试运算符in,测试数组中是否包含某个元素
    def __contains__(self,v):
        return v in self.__value

    #模拟向量内积
    def dot(self,v):
        if not isinstance(v,MyArray):
            print(v,' must be an instance of MyArray.')
            return
        if len(v) != len(self.__value):
            print('The size must be equal.')
            return
        return sum([i*j for i,j in zip(self.__value,v.__value)])

    #重载运算符==,测试两个数组是否相等
    def __eq__(self,v):
        assert isinstance(v,MyArray),'wrong type'
        return self.__value == v.__value

    #重载运算符<,比较两个数组大小
    def __lt__(self,v):
        assert isinstance(v,MyArray),'wrong type'
        return self.__value < v.__value

if __name__ == '__main__':
    print('Please use me as a module.')


    





            
posted @ 2019-09-11 12:59  旅人_Eric  阅读(193)  评论(0编辑  收藏  举报