26 复合赋值算术运算符:
__iadd__(self,rhs) +=
__isub__(self,rhs) -=
__imul__(self,rhs) *=
当__imul__重载后调用重载后的,如果没有,则调用__mul__
__itruediv__(self,rhs) /=
__ifloordiv__(self,rhs) //=
__imod__(self,rhs) %=
__ipow__(self,rhs) **=
示例1 class MyList:
def __init__(self, vaule): '''传入参数可变时,必须用拷贝,这样拿到的数据才为此对象所有,否则只是两个变量绑定到一份数据, 改变原有数据时将改变对象属性的值,这是不允许的''' self.vaule = vaule.copy()
def __str__(self): return 'MyList(' + str(self.vaule) + ')'
def __mul__(self,other): return MyList(self.vaule * other)
l1 = MyList([1,2,3]) l1 *=2 print(l1) 执行结果 MyList([1, 2, 3, 1, 2, 3]) |
||
示例1 class MyList:
def __init__(self, vaule): '''传入参数可变时,必须用拷贝,这样拿到的数据才为此对象所有,否则只是两个变量绑定到一份数据, 改变原有数据时将改变对象属性的值,这是不允许的''' self.vaule = vaule.copy()
def __str__(self): return 'MyList(' + str(self.vaule) + ')'
def __mul__(self,other): return MyList(self.vaule * other)
l1 = MyList([1,2,3]) l1 *=2 print(l1) 执行结果 MyList([1, 2, 3, 1, 2, 3])
示例2 class MyList:
def __init__(self, vaule): '''传入参数可变时,必须用拷贝,这样拿到的数据才为此对象所有,否则只是两个变量绑定到一份数据, 改变原有数据时将改变对象属性的值,这是不允许的''' self.vaule = vaule.copy()
def __str__(self): return 'MyList(' + str(self.vaule) + ')'
def __mul__(self,other): return MyList(self.vaule * other)
def __imul__(self,rhs): self.vaule = self.vaule*rhs
l1 = MyList([1,2,3]) l1 *=2 print(l1) MyList([1, 2, 3, 1, 2, 3]) |
27 一元运算符
__neg__ +正
__pos__ -负
__invert__ ~取反
27.1 重载方法
def __xxx__(self,lhs):
语句
class MyList:
def __init__(self, v): self.value = v.copy()
def __str__(self): return 'MyList('+str(self.value)+')'
def __neg__(self):
for i in range(len(self.value)): self.value[i] = -self.value[i] return MyList(self.value)
L1 = MyList([1,2,3]) L2 = -L1 #实现MyList([-1,-2,-3]) print(L2)
class MyList:
def __init__(self, v): self.value = v.copy()
def __str__(self): return 'MyList(' + str(self.value) + ')'
def __neg__(self):
for i in range(len(self.value)): self.value[i] = -self.value[i] return MyList(self.value)
mi = MyList(self.value)
mi.value.reverse() return MyList(mi.value)
L1 = MyList([1, 2, 3]) L3 = ~L1 # 实现MyList([3,2,1]) print(L3) |
28 比较运算符的重载:
__lt__ <
__le__ <=
__gt__ >
__ge__ >=
__eq__ ==
__ne__ !=
28.1 比较运算符通常返回True或False
29 位运算符重载:
__invert__ ~取反
__and__ &位与
__or__ |位或
__xor__ ^位异或
__lshift__ <<左移位
__rshift__ >>右移位
30 内建函数的重载:
__abs__ 绝对值
__len__ 长度
__reversed__ 反转
__round__ 对数进行四舍五入
·····
31 集合运算符
32 数值转换函数重载
str(obj) __str__
complex(obj) __complex__
int(obj) __int__
float(obj) __float__
bool(obj) __bool__
32.1 浮点类型示例
class MyFloat:
def __init__(self, n): self.data = n
def __float__(self):
n = MyFloat('100') print(float(n)) 执行结果 100 |
32.2 bool测试运算符重载
32.2.1方法格式:
def __bool__(self):
·····
32.2.2作用:
用if语句的真值测试表达式中
用于while语句的真值表达式中
用于bool(obj)函数取值
32.2.3说明:
当没有__bool__(slef)方法时,真值测试将以__len__(self)的方法的返回值来进行测试bool值
如果__bool__(self)和__len__(self)同时重载,则以__bool__(slef)为准
32.2.3 示例
class MyList:
def __init__(self, count=0, value=0): self.data = [] for x in range(count): self.data.append(value)
def __repr__(self): return 'MyList(' + repr(self.data) + ')'
def __bool__(self): for x in self.data: if x: return True return False def __len__(self): return len(self.data)
a = MyList(10,1) print(bool(a)) |
33 in/not in重载(是否在一个容器中)
33.1 重载方法
def __contains__(slef,e):
········
33.2 示例
class even: '''偶数类,用于显示偶数是否在有序列表中'''
def __init__(self, begin, end): self.begin = begin self.end = end # 不包含end def __contains__(self,e): if e<self.begin or e> self.end: return False if e%2 == 0: return True return False
e1 = even(1, 10) #e1中的值为[2,4,6,8] # Traceback (most recent call last): # File "in_even.py", line 11, in <module> # if 4 in e1: # TypeError: argument of type 'even' is not iterable
if 3 in e1: print("4在even(1,10)中") else: print("3不在even(1,10)中") |
练习: class Primes:
def __init__(self, end): self.begin = 2 self.end = end
def __contains__(self, e): if e < self.begin or self.end < e: return False if e == 2: return False for x in range(2, e): if e % x == 0: return False return True
p1 = Primes(100) if 3 not in p1: print("不是素数") else: print("是素数") #类内直接调用此模块内 并且在类外面的函数 |
34 索引和切片运算符的重载:
34.1 重载方法
__getiterm__(self,i) #用索引/切片获取值
__setiterm__(self,i,value) #设置索引或切片的值
__deliterm__(self,i) #进行删除索引操作
34.2 作用:
让自定义对象能进行索引和切片操作
原有索引功能:
L =[1,2,3,4]
L[2]= 3.14 索引赋值
print(L[2]) 索引取值
del L[2] 删除索引
34.3 示例
索引示例 class MyList:
def __init__(self, count=0, value=0): self.data = [] for x in range(count): self.data.append(value)
def __repr__(self): return 'MyList(' + repr(self.data) + ')'
def __getitem__(self, index): # ml = MyList() # ml.data = self.data[index] # return ml return self.data[index] # 返回索引所对应的值
def __setitem__(self, index, value): self.data[index] = value # return self
def __delitem__(self, index): del self.data[index] # return self # 此时del函数做了两件事,删除索引,并重新制索引
myl = MyList(5, 1) myl[1] = 2 print(myl) print(myl[1]) |
切片示例 class MyList:
def __init__(self, count=0, value=0): self.data = [] for x in range(1, 6): self.data.append(x)
def __repr__(self): return 'MyList(' + repr(self.data) + ')'
def __getitem__(self, index): return self.data[index] # 返回索引所对应的值
def __setitem__(self, index, value): self.data[index] = value # return self
def __delitem__(self, index): del self.data[index] # return self # 此时del函数做了两件事,删除索引,并重新制索引
myl = MyList(5, 1) print(myl[1:5:2]) # index = slice(1,5,2) # myl[index] index可以是切片 print(myl[slice(1, 5, 2)]) |
|
35 函数调用模拟重载
__call__方法
35.1 作用:
让一个对象能像函数一样调用
35.2 方法格式
def__call__(self,参数列表):
·········
注:此重载方法的参数可以是1个或多个
class MySum: # def __call__(self): # '''函数调用''' # print("__call__") # return 100
# def __call__(self,a,b): # '''函数调用''' # print("__call__") # return a+b def __init__(self): self.data = 0 def __call__(self, *args, **kwargs): print('args:', args, 'kwargs:', kwargs) s = sum(args) self.data += s return s
mys = MySum() r = mys(100, 200) # 对象可以像方法一样调用 print(r) print(mys.data) |
36 属性管理重载
属性管理函数
getattr(obj,name)
setattr(obj,name,value)
hastattr(obj,name[,defalut])
delattr(obj,name)
36.1 作用
实现对特殊属性的管理
模拟一些特殊属性
36.2 重载格式:
def__setattr__(self,n,v): #设置属性
··········
def __getattribute__(self,n,): #获取属性
··········
def__getattr__(self,n):
·······
在__getattribute__产生AttributeError异常时重载新尝试获取属性
def__delattr__(self,n): #删除属性
·········
注:以上四个方法当属性不存在时,需要产生AttributeError异常错误
36.3 示例
# 1.写一个正方形类: # 有三个属性: # 边长是:length # 周长: zhouchang # 面积:area # 要求:用此类生成对象,此三个属性中一个变化,其他属性同步变化 class Square:
length = 0 # 类属性,对象也能调用
def __init__(self, l): self.__class__.length = l
def __setattr__(self, name, value): if name == 'perimeter': self.__class__.length = (value / 4) else: self.__class__.length = value
def __getattr__(self, name): if name == 'perimeter': return self.__class__.length * 4
def __delattr__(self,name): if name == 'perimeter': print("不允许删除此属性") raise AttributeError
sq = Square(10) print(sq.length) sq.perimeter = 400 #perimeter属性是不存在的.属性赋值 print(sq.length) print(sq.perimeter)
del sq.perimeter |
36.4 说明:
__getattr__是在找不到对应属性时才调用,当没有属性时需要产生AttributeError错误
__getattribute__在任何时候都会被调用,当没有属性时需要产生AttributeError错误,然后进入__getattr__继续寻找
37 迭代器(高级)
37.1 迭代器协议
迭代器协议是指对象(能够)使用next函数获取下一项数据,在没有下一项数据时,触发一个StopIteration异常,来终止迭代的约定
next(it) 对应__next__(self)方法
iter(obj) 对应__iter__(self)方法,通常返回一个可迭代对象
补充:for 语句和推导式,先调用iter(obj)拿出迭代器
range() 生成器函数
xfor x in range() 生成器表达式
37.2 示例
class Odd: # odd 奇数
def __init__(self, begin, end): self.begin = begin self.end = end self.cur = begin
def __next__(self): print("__next__被调用") if self.cur >= self.end: raise StopIteration r = self.cur self.cur += 2 return r
def __iter__(self): # self本身是生成器 self本身也是迭代器,for循环必须#根据此方法拿到迭代器 self.cur = self.begin # 每次循环先调用一遍此函数,在调用__next__函数 return self
odd = Odd(1, 10)
print(next(odd)) # 1 print(next(odd)) # 3 print(next(odd)) # 5 |
37 异常(高级)
with 语句
37.1 语法:
with 表达式[as 变量]:
语句块
或
with 表达式1 [as 变量名1][,表达式2 [as 变量名2]······]
语句块
37.2 说明:
as 子句中的变量绑定生成的对象
37.3 作用:
适用于对资源进行访问的场合,确保使用过程中不管是否发生异常,都会执行必须的清理操作,并释放资源
37.4 示例
textWith.txt: aaaaaa bbbbbb cccccc dddddd
with open("textWith.txt", 'r') as f: while True: l = f.readline().lstrip() print(l, end = '') if len(l) == 0: break print()
执行结果 aaaaaa bbbbbb cccccc dddddd #交给文件管理器进行管理,不管有无异常文件均能关闭文件, #目前只有文件能如此 |