4.2.1 自定义数组

  任务:自定义一个数组类,支持数组与数字之间的四则运算,数组之间的加法运算、内积运算、和大小比较,数组元素访问和修改,以及成员测试等功能。

  1 class MyArray():
  2     '''All the elements in this array must be numbers'''
  3 
  4     def __IsNumber(self,n):
  5         if not isinstance(n,(int,float,compile)):
  6             return False
  7         return True
  8 
  9     #构造函数,进行必要的初始化
 10     def __init__(self,* args):
 11         if not args:
 12             self.__value = []
 13         else:
 14             for arg in args:
 15                 if not self.__IsNumber(arg):
 16                     print('All elements must be numbers')
 17                     return
 18 
 19         # 将传递进来的参数从tuple类型转换为list类型,这样就能进行后续的操作了。
 20         self.__value = list(args)
 21 
 22     #定义一个析构函数,当该类没有实例的时候,释放内部封装的列表
 23     def __del__(self):
 24         del self.__value
 25 
 26 
 27     #重载运算符 +
 28     #数组中每个元素都与数字n相加,或两个数组相加,返回新数组
 29     def __add__(self,n):
 30         if self.__IsNumber(n):
 31             #数组中所有元素都与数字n相加
 32             b = MyArray()
 33             b.__value = [item + n for item in self.__value]
 34             return b
 35 
 36         elif isinstance(n,MyArray):
 37             #两个等成的数组对应元素相加
 38             if len(n.__value) == len(self.__value):
 39                 c = MyArray()
 40                 c.__value = [i + j for i,j in zip(self.__value,n.__value)]
 41 
 42                 #或者用把列表推导改成for遍历,不过还是推导的执行效率高
 43                 #for i,j in zip(self.__value,n.__value):
 44                 #    c.__value.append(i + j
 45 
 46                 return c
 47 
 48             else:
 49                 print('Length not equal')
 50 
 51         else:
 52             print('Not supported')
 53 
 54 
 55     #重载运算符 -
 56     #数组中每个元素都与数字n相减,返回新数组
 57     def __sub__(self,n):
 58         if not self.__IsNumber(n):
 59             print('- operating with',type(n),'and number type is not supported.')
 60             return
 61 
 62         b = MyArray()
 63         b.__value = [item - n for item in self.__value]
 64         return b
 65 
 66     #重载运算符 *
 67     #数组中每个元素都与数字n相乘,返回新数组
 68     def __mul__(self,n):
 69         if not self.__IsNumber(n):
 70             print('* operating with',type(n),'and number type is not supported.')
 71             return
 72 
 73         b = MyArray()
 74         b.__value = [item * n for item in self.__value]
 75         return b
 76 
 77     #重载运算符 /
 78     #数组中每个元素都与数字 n 相除,返回新数组
 79     def __truediv__(self,n):
 80         if not self.__IsNumber(n):
 81             print(r'/ operating with', type(n), 'and number type is not supported.')
 82             return
 83 
 84         b = MyArray()
 85         b.__value = [item / n for item in self.__value]
 86         return b
 87 
 88 
 89     # 重载运算符 //
 90     # 数组中每个元素都与数字 n 整除,返回新数组
 91     def __floordiv__(self, n):
 92         if not self.__IsNumber(n):
 93             print(r'// operating with', type(n), 'and number type is not supported.')
 94             return
 95 
 96         b = MyArray()
 97         b.__value = [item // n for item in self.__value]
 98         return b
 99 
100     # 重载运算符 %
101     # 数组中每个元素都与数字 n 取余,返回新数组
102     def __mod__(self, n):
103         if not self.__IsNumber(n):
104             print('% operating with', type(n), 'and number type is not supported.')
105             return
106 
107         b = MyArray()
108         b.__value = [item % n for item in self.__value]
109         return b
110 
111         # 重载运算符 **
112         # 数组中每个元素都与数字 n 进行幂计算,返回新数组
113     def __pow__(self, n):
114         if not self.__IsNumber(n):
115             print('% operating with', type(n), 'and number type is not supported.')
116             return
117 
118         b = MyArray()
119         b.__value = [item ** n for item in self.__value]
120         return b
121 
122     def __len__(self):
123         return len(self.__value)
124 
125 
126     #直接使用该类对象作为表达式来查看对象的值
127     def __repr__(self):
128         return repr(self.__value)
129 
130     #支持使用print()函数查看对象的值
131     def __str__(self):
132         return str(self.__value)
133 
134 
135     #往数组中追加元素
136     def append(self,v):
137         if not self.__IsNumber(v):
138             print('Only number can be appended.')
139             return
140         self.__value.append(v)
141 
142     #获取指定下标的元素值,支持使用列表或元组指定多个下标
143     def __getitem__(self, index):
144         length = len(self.__value)
145         #如果指定单个整数作为下标,则直接返回元素值
146         if isinstance(index,int) and 0 <= index <= length:
147             return self.__value[index]
148 
149         #使用列表或元组指定多个整数下标
150         elif isinstance(index,(list,tuple)):
151             for i in index:
152                 if not (isinstance(i,int) and 0 <= i < length):
153                     return 'index error'
154                 result = []
155 
156                 for item in index:
157                     result.append(self.__value[item])
158                 return result
159         else:
160             return 'index srror'
161 
162     #修改元素值,支持使用列表或元组指定多个下标,同时修改多个元素值
163     def __setitem__(self,index,value):
164         length = len(self.__value)
165 
166         #如果下标合法,则直接修改元素值
167         if isinstance(index,int) and 0 <= index < length:
168             self.__value[index] = value
169 
170         #支持使用列表或元组指定多个下标
171         elif isinstance(index,(tuple,list)):
172             for i in index:
173                 if not (isinstance(i,int) and 0 <= i < length):
174                     raise Exception('index error')
175 
176             #如果下标和给的值都是列表或元组,并且个数一样
177             #则分别为多个下标的元素修改值
178             if isinstance(value,(list,tuple)):
179                 if len(index) == len(value):
180                     for i,v in enumerate(index):
181                         self.__value[v] = value[i]
182                 else:
183                     raise Exception('values and index must be of the same length')
184 
185             #如果指定多个下标和一个普通值,则把多个元素修改为相同的值
186             elif isinstance(value,(int,float,complex)):
187                 for i in index:
188                     self.__value[i] = value
189             else:
190                 raise Exception('value error')
191 
192         else:
193             raise Exception('index error')
194 
195     #支持成员测试运算符 in ,测试数组中是否包含某个元素
196     def __contains__(self,v):
197         if v in self.__value:
198             return True
199         return False
200 
201     #模拟向量内积
202     def dot(self,v):
203         if not isinstance(v,MyArray):
204             print(v,'must be an instance of MyArray.')
205             return
206         if len(v) != len(self.__value):
207             print('The size must be equal.')
208             return
209         return sum([i * j for i,j in zip(self.__value,v.__value)])
210 
211         #或者用如下方式实现
212         #b = MyArray()
213         #for m,n in zip(v.__value,self.__value):
214         #    b.__value.append(m * n)
215         #return sum(b.__value)
216 
217     #重载运算符 == ,测试两个数组是否相等
218     def __eq__(self,v):
219         if not isinstance(v,MyArray):
220             print(v,'must be an instance of MyArray')
221             return False
222         if self.__value == v.__value:
223             return True
224         return False
225 
226     #重载运算符 < ,比较两个数组大小
227     def __lt__(self,v):
228         if not isinstance(v,MyArray):
229             print(v,'must be an instace of MyArray.')
230             return False
231         if self.__value < v.__value:
232             return True
233         return False
234 
235 
236 if __name__ == '__main__':
237     print('Please use me as a module.')

  将上面的程序保存为MyArray.py文件,可以作为Python模块导入并使用其中的数组类。

    >>> import os
    >>> os.getcwd()
    'C:UsersddddAppDataLocalProgramsPythonPython35'
    >>>

  把文件放在这个目录下

  1 >>> 
  2 >>> from MyArray import MyArray
  3 >>> 
  4 >>> #导入模块中自定义的类
  5 >>> from MyArray import MyArray
  6 >>> 
  7 >>> #实例化对象
  8 >>> x = MyArray(1,2,3,4,5,6)
  9 >>> y = MyArray(6,5,4,3,2,1)
 10 >>> 
 11 >>> #返回数组长度,即数组中的元素个数
 12 >>> len(x)
 13 6
 14 >>> 
 15 >>> #每个元素加5,返回新数组,原数组值不改变
 16 >>> x + 5
 17 [6, 7, 8, 9, 10, 11]
 18 >>> 
 19 >>> #每个元素值乘以3,返回新数组
 20 >>> x * 3
 21 [3, 6, 9, 12, 15, 18]
 22 >>> 
 23 >>> #计算两个数组(一维向量)的内积
 24 >>> x.dot(y)
 25 56
 26 >>> 
 27 >>> #在数组尾部追加新元素
 28 >>> x.append(7)
 29 >>> x
 30 [1, 2, 3, 4, 5, 6, 7]
 31 >>> 
 32 >>> #x数组追加新元素后,两个数组元素数不相等,看看进行内积的计算会如何
 33 >>> x.dot(y)
 34 The size must be equal.
 35 >>> 
 36 >>> #试图修改元素值
 37 >>> x[9] = 8
 38 Traceback (most recent call last):
 39   File "<pyshell#30>", line 1, in <module>
 40     x[9] = 8
 41   File "C:UsersddddAppDataLocalProgramsPythonPython35MyArray.py", line 193, in __setitem__
 42     raise Exception('index error')
 43 Exception: index error
 44 >>> #根据报错内容可知,是下标越界了,因为x数组中只有7个元素
 45 >>> 
 46 >>> #x数组中的每个元素值除以 2
 47 >>> x / 2
 48 [0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5]
 49 >>> 
 50 >>> x // 2
 51 [0, 1, 1, 2, 2, 3, 3]
 52 >>> 
 53 >>> x % 3
 54 [1, 2, 0, 1, 2, 0, 1]
 55 >>> 
 56 >>> #返回固定位置的元素值
 57 >>> x[2]
 58 3
 59 >>> 
 60 >>> #测试数组中是否包含某个元素
 61 >>> 'a' in x
 62 False
 63 >>> 
 64 >>> 3 in x
 65 True
 66 >>> 
 67 >>> #比较数组的大小
 68 >>> x < y
 69 True
 70 >>> 
 71 >>> x = MyArray(1,2,3,4,5,6)
 72 >>> 
 73 >>> #两个数组中对应元素相加,返回新数组
 74 >>> x + y
 75 Traceback (most recent call last):
 76   File "<pyshell#54>", line 1, in <module>
 77     x + y
 78   File "C:UsersddddAppDataLocalProgramsPythonPython35MyArray.py", line 30, in __add__
 79     if self.__IsNumber(n):
 80   File "C:UsersddddAppDataLocalProgramsPythonPython35MyArray.py", line 5, in __IsNumber
 81     if not isinstance(n,(int,float,compile)):
 82 TypeError: isinstance() arg 2 must be a type or tuple of types
 83 >>> 
 84 >>> 
 85 >>> #查看多个位置上的元素值
 86 >>> x[[1,3,4]]
 87 [2, 4, 5]
 88 >>> 
 89 >>> 
 90 >>> #同时修改多个元素的值
 91 >>> x[[2.3]] = [8,9]
 92 Traceback (most recent call last):
 93   File "<pyshell#62>", line 1, in <module>
 94     x[[2.3]] = [8,9]
 95   File "C:UsersddddAppDataLocalProgramsPythonPython35MyArray.py", line 174, in __setitem__
 96     raise Exception('index error')
 97 Exception: index error
 98 >>> 
 99 >>> #为多个元素赋值为相同的值
100 >>> x[[1,3,5]] = 0
101 >>> x
102 [1, 0, 3, 0, 5, 0]
103 >>> 
原文地址:https://www.cnblogs.com/avention/p/8652631.html