第三十章 运算符重载

基础知识

以下是对重载背后的关键概念的复习:

  • 运算符重载让类拦截常规的python操作;
  • 类可重载所有python表达式运算符;
  • 类也可重载打印、函数调用、属性访问等内置运算;
  • 重载使类实例的行为更加接近内置类型;
  • 重载是通过在一个类中提供特殊名称的方法来实现的;

构造函数和表达式:__init __和__sub __

class Number():
	def __init__(self, start):
		self.data = start
	def __sub__(self, other):
		return Number(self.data - other)

X = Number(5)
Y = X - 2
print(Y.data)				# output:3

常见的运算符重载方法

方法名实现功能触发调用的形式
__init __构造函数对象创建:X = Class(args)
__del __析构函数X对象回收
__add __‘+’运算符X + Y,X += Y
__or __按位或X / Y
__repr __, __str __打印、转换print(X)、repr(X)、str(X)
__call __函数调用X(*args, **kargs)
__getattr __属性访问X.undefined
__setattr __属性赋值X.any = value
__delattr __属性删除del X.any
__getattribute __属性访问X.any
__getitem __索引、分片、迭代X[key],X[I : j]
__setitem __索引赋值和分片赋值X[key] = value
__delitem __索引删除和分片删除del X[key]
__len __长度len(X)
__bool __布尔测试bool(X)、真值测试
__lt __,__gt __比较X > Y、X < Y、X <= Y、X >= Y、X == Y、X != Y
__le __,__ge __比较X > Y、X < Y、X <= Y、X >= Y、X == Y、X != Y
__eq __,__ne __比较X > Y、X < Y、X <= Y、X >= Y、X == Y、X != Y
__radd __右侧“+”操作other + X
__iadd __原位置“+=”操作X += Y
__iter __,__next __迭代上下文I = iter(X),next(X);for循环
__contains __成员关系测试item in X
__index __整数值转换hex(X)、bin(X)、oct(X)
__enter __,__exit __上下文管理器with obj as var:
__get __,__set __描述符属性X.attr、X.attr = value、del X.attr
__delete __描述符属性X.attr、X.attr = value、del X.attr
__new __创建在__init __之前的对象创建

索引和分片:__getitem __和__setitem __

如果一个类定义(或继承)了__getitem __的话,该方法就会自动调用并进行实例的索引运算;

class Indexer():
	def __getitem__(self, index):
		return index ** 2


X = Indexer()
print(X[2])			# output: 4

拦截分片

__getitem __方法也可以在分片操作时背调用:

class Indexer():
	data = [5, 6, 7, 8]
	def __getitem__(self, index):
		print('getitem:', index)
		return self.data[index]


X = Indexer()
print(X[0])			# output:getitem:0
					#        5

print(X[2, 4])		# output:getitem:silce(2, 4, None)
					# 		 [7, 8]

这里有一点需要解释,index返回值是‘silce(2, 4, None)’

L = [5, 6, 7, 8, 9]
print(L[2, 4])		# output:[7, 8]
print(L[1:])		# output:[6, 7, 8, 9]
print(L[:-1])		# output:[5, 6, 7, 8]
print(L[::2])		# output:[5, 7, 9]

尽管分片对象被绑定到一个分片对象并传递给列表的索引实现。实际上,你总是可以手动地传入一个分片对象,因为分片语法只不过就是用分片对象来索引的语法糖:

print(L[slice(2, 4)])				# output:[7, 8]
print(L[slice(1, None)])			# output:[6, 7, 8, 9]
print(L[slice(None, -1)])			# output:[5, 6, 7, 8]
print(L[slice(None, None, 2)])		# output:[5, 7, 9]

python 3.X中__index__不是索引

不能把python3.X中的索引拦截方法__index__方法混淆起来。__index__方法在使用时会为一个实例返回一个整数值,提供转化数字串的内置函数使用:

class C:
	def __index__(self):
		return 255

X = C()
print(hex(X))		# output:'Oxff'
print(bin(X))		# output:'Ob11111111'
print(otc(X))		# output:'O0377'

索引迭代:getitem

任何会响应索引运算的内置或用户定义的对象,都会响应for循环迭代:

class StepperIndex():
	def __getitem__(self, i):
		return self.data[i]

X = StepperIndex()
X.data = 'spam'
print(X[1])					# output:'p'

for i in X:
	print(item, end=' ')	# output:s p a m

可迭代对象:iter__和__next

用户定义的可迭代对象

class Squares():
	def __init__(self, start, stop):
		self.value = start - 1
		self.stop = stop
	def __iter__(self):
		return self
	def __next__(self):
		if self.value == self.stop:
			raise StopIteration
		self.value += 1
		return self.value ** 2


for i in Squares(1, 5):
	print(i, end=' ')				# output:1, 4, 9, 16, 25

手动迭代对用户自定义的可迭代对象的效果,和内置类型是一样的:

X = Squares(1, 5)
I = iter(X)
next(I)								# output:1
next(I)								# output:4
next(I)								# output:9
next(I)								# output:16
next(I)								# output:25
next(I)								# output:StopIteration

单遍扫面与多遍扫描

我们需要注意的是__iter__被设计为只遍历一次,而不是遍历多次。类在它们的代码中显示地选择扫描行为;

X = Squares(1, 5)
print([n for n in X])				# output:[1, 4, 9, 16, 25]
print([n for n in X])				# output:[]

类vs生成器

要注意上面的例子如果使用生成器函数或生成器表达式编写,则可能变得更加简单一些,它们自动产生可迭代对象并在迭代过程之间保持局部变量状态;
类对于更复杂的迭代建模更胜一筹,尤其当它们能受益于类的一般优越性优势时;

单个对象上的多个迭代器

首先,我们关注一下多重的for循环:

S = 'abc'
for x in S:
	for y in S:
		print(x + y, end=' ' )		# output: aa ab ac ba bb bc ca cb cc

成员关系:containsiter__和__getitem

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值