Python学习笔记九

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Katherine_hsr/article/details/84611697

迭代器函数的重写

迭代器:可以用next(it)函数取值的对象就是迭代器
迭代器协议:迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据触发一个StopIterator来终止迭代的约定
实现方法:
类内需要有__next__(self)方法来实现迭代器协议
语法形式:
class MyIterator:
def next(self):
迭代器协议的实现
return 数据
什么是可迭代对象:是指能用iter(obj)函数返回迭代器的对象(实例);可迭代对象内部一定要定义__iter__(self)方法来返回迭代器。
可迭代对象的语法形式:
class MyIterable:
def iter(self):
语句块
return 迭代器
示例:

# 此示例示意可迭代对象和迭代器的定义及使用方法
class MyList:
	def __init__(self, iterator):
		'''自定义列表类的初始化方法,此方法创建一个data实例变量来绑定一个用来存储数据的列表'''
		self.data = list(iterator)

	def __repr__(self):
		'''此方法为了打印此列表的数据'''
		return "MyList(%r)" % self.data

	def __iter__(self):
		'''有此方法就是可迭代对象,但要求必须返回迭代器'''
		print("__iter__方法被调用")
		return MyListIterator(self.data)

class MyListIterator:
	'''此类用来创建一个迭代器对象,用此迭代器对象可以访问MyList类型的数据'''
	def __init__(self, iter_data):	
		self.cur = 0 	# 设置迭代器的初始值为0代表列表索引
		self.it_data = iter_data 	# it_data绑定要迭代的列表

	def __next__(self):
		'''有此方法的对象才叫迭代器,此方法一定要实现迭代器协议'''
		# 如果self.cur已经超出了列表的索引范围就报迭代结束
		if self.cur >= len(self.it_data):
			raise StopIteration
		# 否则尚未迭代完成,需要返回数据
		r = self.it_data[self.cur] # 拿到要送回去的数
		self.cur = self.cur + 1 	# 将当期值向后移动一个单位
		return r

myl = MyList([2, 3, 5, 7])
print(myl)

for x in myl:
	print(x)   
异常(with)

异常相关语句:
try-except # 用来捕获异常通知
try-finally # 用来做一定要做的事情
raise # 用来发生异常通知
assert # 用来根据条件发出AssertionError类型的异常通知
with语句:
语法:
with 表达式1[as 变量1], 表达式2[as 变量2]:
语句块
作用:使用于对资源进行访问的场合,确保使用过程中不管是否发生异常,都会执行必须的’清理’操作,并释放资源。
如:文件使用后自动关闭,线程中锁的自动获取和释放等
示例:

# 此示例示意try-except和try-finally组合来对文件进行操作

def read_from_file(filename='/Users/huoshirui/Desktop/test/code/practice/info.txt'):
	try:
		f = open(filename)
		try:
			print("reading from file")
			n = int(f.read())
			print("n=", n)
		finally:
			f.close()
			print("close file")
	except OSError:
		print("fail to open file")

read_from_file()



# 用with语句可以实现上面同样的功能
# 此示例示意用try-except和with语句组合来实现文件的操作

def read_from_file(filename='/Users/huoshirui/Desktop/test/code/practice/info.txt'):
	try:
		with open(filename) as f:
			print("reading from file")
			n = int(f.read())
			print("n=", n)
			print("close file")
	except OSError:
		print("fail to open file")

read_from_file()

说明:能够用于with语句进行管理的对象必须是环境管理器

环境管理器

(1)类内有__enter__和__exit__实例方法的类创建的类被称为管理器; (2)能够用with语句管理的对象必须是环境管理器; (3)__enter__方法将在进入with语句时被调用,并返回由as变量管理的对象;(4)__exit__将在离开with语句时被调用,且可以用参数来判断在离开with语句时是否有异常发生并做出相应的处理
示例:


class A:
	def __enter__(self):
		print("已进入with语句")
		return self 		# 返回的对象将由as绑定
	
	def __exit__(self, exc_type, exc_val, exc_tb):
		'''此方法会在退出with语句时自动调用 exc_type在没有异常时为None,在出现异常时为异常类型;exc_val在没有异常时为None,在出现异常时绑定错误对象;exc_tb在没有异常时为None,在出现异常时绑定traceback对象'''
		if exc_type is None:
			print("已离开with语句")
		else:
			print("已离开with语句,离开时状态异常")	
			print("异常类型是:", exc_type)
			print("错误对象是:", exc_val)
			print("traceback是:", exc_tb)

a = A()
with A() as a:
	print("这是with语句内的一条语句")
	int(input("请输入整数"))
对象的属性管理函数
# 从一个对象得到对象的属性;getattr(x, 'y')等同于x.y;当属性不存在时,如果给出default参数,
# 则返回default,如果没有给出default,则参数一个AttributeError错误
getattr(obj, name[, default]) 		

# 用给定的name返回对象obj是否有此属性,此种做法可以避免在getattr(obj, name)时引发错误
hasattr(obj, name)

# 给对象obj的名为name的属性设置相应的值value, set(x, 'y', v)等同于x.y=v
setattr(obj, name, value)

# 删除对象obj中的name属性,delattr(x, 'y')等同于del x.y
delattr(obj, name)


class Dog:
	pass

dog1 = Dog()
# dog1.color会出错
print(getattr(dog1, 'color', 'no color attribute')) # no color

dog1.color = 'white'
print(getattr(dog1, 'color', 'no color attribute')) # white

print(hasattr(dog1, 'color'))		# True

setattr(dog1, 'age', 1)
print(hasattr(dog1, 'age')) 		# True

delattr(dog1, 'age')
print(hasattr(dog1, 'age'))			# False
运算符重载

让自定义的类生成的对象(实例)能够使用运算符进行操作
作用:让自定义的类的实例像内建对象一样运行运算符操作;让程序简洁易读;对自定义的对象,将运算符赋予新的运算规则
算术运算符的重载:
add(self, rhs) self+rhs 加法
sub(self, rhs) self-rhs 减法
mul(self, rhs) self*rhs 乘法
truediv(self, rhs) self/rhs 除法
floordiv(self, rhs) self//rhs 地板除法
mod(self, rhs) self%rhs 求余
pow(self, rhs) self**rhs 幂运算
注:rhs(right hands side)
示例:

# 此示例示意运算符重载与实例方法的相同点和不同点

class MyNumber:
	def __init__(self, v):
		self.data = v

	def __repr__(self):
		return "MyNumber(%d)" % self.data

	# def myadd(self, other):
	# 	v = self.data + other.data
	# 	return MyNumber(v)

	def __add__(self, other):
		print("__add__被调用")
		v = self.data + other.data
		return MyNumber(v)

	def __sub__(self, other):
		v = self.data - other.data
		return MyNumber(v)

n1 = MyNumber(100)
n2 = MyNumber(200)
# n3 = n1.myadd(n2)
#n3 = n1.__add__(n2)
n3 = n1 + n2
print(n3)

n4 = n3 - n2
print(n4)
反向算术运算符的重载

当左手边的类型为内建类型,右手边为自定义类型时,要实现运算必须用以下方法重载
反向算术运算符的重载:
radd(self, lhs) lhs+self 加法
rsub(self, lhs) lhs-self 减法
rmul(self, lhs) lhs*self 乘法
rtruediv(self, lhs) lhs/self 除法
rfloordiv(self, lhs) lhs//self 地板除法
rmod(self, lhs) lhs%self 求余
rpow(self, lhs) lhs**self 幂运算
示例:

# 实现两个自定义列表相加:
class MyList:
	def __init__(self, iterable):
		self.data = list(iterable)

	def __repr__(self):
		return "MyList(%r)" % self.data

	def __add__(self, rhs):
		lst = self.data + rhs.data
		return MyList(lst)

	def __mul__(self, rhs): # rhs绑定整数
		return MyList(self.data * rhs)

	def __rmul__(self, lhs):
		print("__rmul__被调用")
		return MyList(self.data * lhs)

L1 = MyList([1, 2, 3])
L2 = MyList([4, 5, 6])
L5 = L1 * 2		# L1.__mul__(2)
print(L5)   # MyList([1, 2, 3, 1, 2, 3])

L6 = 2 * L1
print(L6)		# 2.__mul__(L1)

复合赋值算术运算符的重载
iadd(self, rhs) self+=rhs 加法
isub(self, rhs) self-=rhs 减法
imul(self, rhs) self*=rhs 乘法
itruediv(self, rhs) self/=rhs 除法
ifloordiv(self, rhs) self//=rhs 地板除法
imod(self, rhs) self%=rhs 求余
ipow(self, rhs) self**=rhs 幂运算
示例:

class MyList:
	def __init__(self, iterable):
		self.data = list(iterable)

	def __repr__(self):
		return "MyList(%r)" % self.data

	def __add__(self, rhs):
		return MyList(self.data + rhs.data)

	def __iadd__(self, rhs):
		print("__iadd__被调用")
		self.data.extend(rhs.data)
		return self.data


L1 = MyList([1, 2, 3])
L2 = MyList([4, 5, 6])

L1 += L2		# 当没有__iadd__方法时,等同于调用L1 = L1 + L2
print(L1)		# [1, 2, 3, 4, 5, 6]
比较运算符的重载

lt(self, rhs) self < rhs 小于
le(self, rhs) self <= rhs 小于等于
gt(self, rhs) self > rhs 大于
ge(self, rhs) self >= rhs 大于等于
eq(self, rhs) self == rhs 等于
ne(self, rhs) self != rhs 不等于
注:比较运算符通常返回True或False

位运算符重载

invert(self) ~self 取反(一元运算符)
and(self, rhs) self & rhs 位与
or(self, rhs) self | rhs 位或
xor(self, rhs) self ^ rhs 位异或
lshift(self, rhs) self << rhs 左移
rshift(self, rhs) self >> rhs 右移

反向位运算符重载

rand(self, lhs) lhs & self 位与
ror(self, lhs) lhs | self 位或
rxor(self, lhs) lhs ^ self 位异或
rlshift(self, lhs) lhs << self 左移
rrshift(self, lhs) lhs >> self 右移

复合赋值位运算符重载

iand(self, rhs) self &= rhs 位与
ior(self, rhs) self |= rhs 位或
ixor(self, rhs) self ^= rhs 位异或
ilshift(self, rhs) self <<= rhs 左移
irshift(self, rhs) self >>= rhs 右移

一元运算符的重载

neg(self) - self 负号
pos(self) + self 正号
invert(self) ~ self 取反

一元运算符的重载方法

class 类名:
def XXX(self):

示例:

# 此示例示意一元运算符的重载

class MyList:
	def __init__(self, iterable):
		print("__init__被调用")
		self.data = list(iterable)

	def __repr__(self):
		return "MyList(%r)" % self.data

	def __neg__(self):
		'''此方法用来制定-self返回的规则'''
		#L = [-x for x in self.data]
		L = (-x for x in self.data)
		return MyList(L)
	


L1 = MyList([1, 2, 3])
L2 = -L1
print(L2)

运算符重载说明:运算符重载不能改变运算符的优先级
Python类名最好用驼峰命名法:
MyList MyRange 大驼峰(所有单词首字母大写,其余小写)
getstudentAge 小驼峰(第一个单词首字母小写,其他大写)

in / not in 运算符的重载

重载方法:
contains(self, e): e in self 成员运算
示例:

class MyList:
	def __init__(self, iterable):
		self.data = list(iterable)

	def __repr__(self):
		return "MyList(%r)" % self.data

	def __contains__(self, e):
		'''此方法用来实现in/not in的运算符的重载'''
		for x in self.data:
			if x == e:
				return True
		return False


L1 = MyList([1, 2, 3])
if 2 in L1:
	print("2 在L1中")
else:
	print("2 不在L1中")

if -1 not in L1:
	print("-1 不在L1中")
else:
	print("-1 在L1中")
索引和切片运算符的重载

getitem(self, i) x = self[i] 索引/切片取值
setitem(self, i, v) self[i] = v 索引/切片赋值
delitem(self, i) del self[i] del语句删除索引等
作用:让自定义类型的对象能够支持索引和切片操作
示例:

# 此示例示意[]运算符的重载

class MyList:
	def __init__(self, iterable):
		print("__init__被调用")
		self.data = list(iterable)

	def __repr__(self):
		return "MyList(%r)" % self.data

	def __getitem__(self, i):
		print("__getitem__被调用, i = ", i)
		return self.data[i]

	def __setitem__(self, i, v):
		print("__setitem__被调用, i = ", i, "v = ", v)
		self.data[i] = v	# 修改data绑定的列表


L1 = MyList([1, 2, 3])
v = L1[0]
print(v)

L1[1] = 2 	# 等同于调用L1.__setitem__(1, 2)
print(L1[1])
slice 函数

作用:用于创建一个Slice切片对象,此对象存储一个切片的起始值,终止值和步长信息
slice(start, stop=None, step=None) 创建一个切片对象
slice的对象的属性:
s.start 切片起始值,默认为None
s.stop 切片终止值,默认为None
s.step 切片步长,默认为None
示例:

lass MyList:
	def __init__(self, iterable):
		print("__init__被调用")
		self.data = list(iterable)

	def __repr__(self):
		return "MyList(%r)" % self.data

	def __getitem__(self, i):
		print("__getitem__被调用, i = ", i)
		if type(i) is int:
			print("正在做索引操作")
		elif type(i) is slice:
			print("正在做切片操作")
		else:
			raise KeyError
		return self.data[i]

	
L1 = MyList([1, 2, 3, 4, 5, 6])
print(L1[::2])		# 等同于调用L1[slice(None, None, 2)]

猜你喜欢

转载自blog.csdn.net/Katherine_hsr/article/details/84611697