函数重载 overwrite
在自定义的类内添加相应的方法,让自定义的类生成的对象(实例)像内建对象一样进行函数操作。
repr(x) 返回一个能代表此对象的表达式字符串,通常:eval(repr(obj)) = obj
str(obj) 通过给定对象,返回一个字符串(这个字符串通常是给人阅读的)
换句话说
repr(obj) 返回的字符串是给python用的
str(obj) 返回的字符串是给人看的
repr()和str()的重载方法
repr() 函数的重载方法
def __repr__(self):
...
return 字符串
str() 函数的重载方法
def __str__(self):
...
return 字符串
str(obj) 函数调用方法说明
a、str(obj) 函数先查找obj.__str__() 方法,调用此方法并返回结果
b、如果obj.__str__() 方法不存在,则调用obj.__repr__()方法并返回结果
c、如果obj.__repr__方法不存在,则调用object类的__repr__实例方法显示<__main__.MyNumber object at xxx> 格式的字符串
示例
class MyNumber:
def __init__(self, value):
self.data = value
def __str__(self):
# print('正在调用__str__方法,转换为普通字符串')
s = "自定义数据:%d" % self.data
return s
def __repr__(self):
'''此方法供repr(obj)函数调用'''
return 'MyNumber(%d)' % self.data
n1 = MyNumber(100)
print(str(n1)) # 此句等同于print(n1)
print(n1)
print(repr(n1))
__abs__ abs(obj) 函数调用
__len__ len(obj) 函数调用
__reversed__ reversed(obj) 函数调用
__round__ round(obj) 函数调用
示例
class MyInteger:
def __init__(self, v):
self.data = v
def __repr__(self):
return 'MyInteger(%d)' % self.data
def __abs__(self):
'''此方法用于制定abs(obj) 函数取值时返回的结果'''
if self.data < 0:
# 用-self.data 创建一个新的对象返回回去
t = MyInteger(-self.data)
return t
return MyInteger(self.data)
def __len__(self):
'''len(obj) 函数规定只能返回整数值,
因此此方法不能返回字符串等其他类型的值'''
return 10
i1 = MyInteger(-100)
print(i1) # 等同于print(str(i1))
n = abs(i1)
print(n) # MyInteger(100)
print(len(i1)) # 等同于print(i1.__len__())
__complex__ complex(obj) 函数调用
__int__ int(obj) 函数调用
__float__ float(obj) 函数调用
__bool__ bool(obj) 函数调用
用于bool(obj) 函数取值
用于if语句真值表达式中
用于while语句的值表达式中
重载方法
def __bool__(self):
...
说明
a、当自定义类内有__bool__(self) 方法时,以此方法的返回值作为bool(obj) 的返回值
b、当不存在__bool__ (self) 方法时,bool(x) 返回 __len__(self) 方法的返回值是否为零来测试布尔值
c、当再不存在__len__(self)方法时,则直接返回True
示例
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
return "MyList(%s)" % self.data
def __len__(self):
print("__len__被调用")
return len(self.data)
def __bool__(self):
'''此方法用来制定一个bool(x) 返回的规则'''
# 如果没有任何元素返回False
print("__bool__方法被调用")
if len(self.data) == 0:
return False
for x in self.data:
if x:
return True
return False
myl = MyList([1, -2, 3, -4])
print(myl)
print(bool(myl)) # False
print(len(myl))
myl1 = MyList([0, 0.0, False, None])
print(bool(myl1)) # False
myl2 = MyList([0, 1, 2])
print(bool(myl2)) # True
可以通过next函数取值的对象就是迭代器
迭代器协议
迭代器协议是指对象能够使用next函数获取下一个数据,在没有下一项数据时触发一个StopIteration异常来终止迭代的约定
迭代器的实现
通过__next__(self) 方法用来实现迭代器协议
重载方法
class MyIterator:return 数据
可迭代对象内部要定义__iter__(self) 方法来返回迭代器对象
重写方法
class MyIterable: 指定迭代器
# 此示例示意用自定义的类MyRange实现可迭代对象
# 用自定义的类MyIterator 实现迭代器
class MyIterator:
def __init__(self, start, stop, step):
# self.start变量用来记录迭代器的起始位置和当前位置
self.start = start
self.stop = stop
self.step = step
def __next__(self):
'''此方法用于实现迭代器协议'''
print("MyIterator.__next__方法被调用!")
if self.start >= self.stop: # 迭失终止条件
raise StopIteration
r = self.start # 先将要返回的数存于变量r中
self.start += self.step # 迭代器后移
return r # 送回给next(it) 调用
class MyRange:
def __init__(self, start, stop=None, step=1):
if stop is None:
stop = start
start = 0
self.start = start # 起始值
self.stop = stop # 终止值
self.step = step # 步长
def __repr__(self):
return "MyRange(%d, %d, %d)" % (self.start,self.stop, self.step)
def __iter__(self):
'''此方法用于把MyRange类型创建的对象当做可迭代对象'''
print("__iter__被调用")
# 此处必须返回迭代器
return MyIterator(self.start, self.stop, self.step)
L = [x for x in MyRange(5, 10)]
print(L)
print('----------------------------')
R = MyRange(5, 10, 2)
it = iter(R) # R.__iter__
print(next(it)) # it.__next__
指定自身既是迭代器又是可迭代对象
# 此示例示意用自定义的类MyRange实现可迭代对象和实现迭代器
class MyRange:
def __init__(self, start, stop=None, step=1):
if stop is None:
stop = start
start = 0
self.start = start # 起始值
self.stop = stop # 终止值
self.step = step # 步长
def __repr__(self):
return "MyRange(%d, %d, %d)" % (self.start,self.stop, self.step)
def __iter__(self):
'''此方法用于把MyRange类型创建的对象当做可迭代对象'''
print("__iter__被调用")
return self
def __next__(self):
'''此方法用于实现迭代器协议'''
print("MyIterator.__next__方法被调用!")
if self.start >= self.stop: # 迭失终止条件
raise StopIteration
r = self.start # 先将要返回的数存于变量r中
self.start += self.step # 迭代器后移
return r # 送回给next(it) 调用
L = [x for x in MyRange(5, 10)]
print(L)
print('----------------------------')
R = MyRange(5, 10, 2)
it = iter(R) # R.__iter__
print(next(it)) # it.__next__
d、__exit__ 将在离开with语句时被调用, 且可以用参数来判断在离开with语句时是否有异常发生并做出相应的处理
# 本程序示意自定义的类作为环境管理器使用
class FileWriter:
def __init__(self, filename):
self.filename = filename # 此属性用于记住文件名
def writeline(self, s):
'''此方法用于向文件内写入字符串,同时自动添加换行'''
self.file.write(s)
self.file.write('\n')
def __enter__(self):
'''此方法用于实现环境管理器'''
self.file = open(self.filename, 'w')
print("已进入__enter__方法,文件打开成功")
return self # 返回值向用于 with中的as 绑定
def __exit__(self, exec_type, exec_value, exec_tb):
'''
exec_type 为异常类异,没有异常发生时为None
exec_value 为错误的对象,没有异常时为None
exec_tb 为错误的traceback对象
'''
self.file.close()
print("文件", self.filename, "已经关闭")
if exec_type is None:
print("退出with时没有发生异常")
else:
print("退出with时,有异常,类型是", exec_type,"错误是", exec_value)
print("__exit__法被调用,已离开with语句")
try:
with FileWriter('log.txt') as fw:
while True:
s = input("请输入一行: ")
if s == 'exit':
break
if s == 'error':
raise ValueError("故意制造的值错误")
fw.writeline(s)
except:
print("有错误发生,已转为正常")
print("这是with语句之外,也是程序的最后一条语句")
让自定义的类生成的对象(实例)能够实例运算符进行操作
作用
a、让自定义类的实例像内建对象一样进行运算符操作c、对自定义的对象将运算符赋予新的运算规则
说明
运算符重载方法的参数已经有固定的含义,不建议改变原有的意义
方法名 运算符和表达式 说明
__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) 右手边
二元运算符重载方法格式
def __xxx__(self, other):
...
示例
# 此示例示意自定义的类通过运算符重载实现运算符操作
class MyNumber:
def __init__(self, v):
self.data = v
def __repr__(self):
return "MyNumber(%d)" % self.data
def __add__(self, other):
'''实现加法操作,生成一个新的对象并返回给调用者'''
print("__add__方法被调用")
return MyNumber(self.data + other.data)
def __sub__(self, rhs):
return MyNumber(self.data - rhs.data)
n1 = MyNumber(100)
n2 = MyNumber(200)
n3 = n1 + n2 # 等同于n1.__add__(n2)
# n3 = n1.__add__(n2)
print(n1, "+", n2, '=', n3) # MyNumber(300) ???
n4 = n1 - n2
print('n4 =', n4)
当运算符的左侧为内建类型时,右侧为自定义类型进行算术运算时,会出现TypeError错误,因无法修改内建类型的代码来实现运算符重载,此时需要使用反向算术运算符重载来完成重载。
反向算术运算重载
方法名 运算符和表达式 说明__rpow__(self, lhs) lhs ** self 冪运算
示例
class MyNumber:
def __init__(self, v):
self.data = v
def __repr__(self):
return "MyNumber(%d)" % self.data
def __sub__(self, rhs):
'''实现减法操作,生成一个新的对象并返回给调用者'''
print("__sub__方法被调用")
return MyNumber(self.data - rhs)
def __rsub__(self, lhs):
'''实现被减操作,生成一个新的对象并返回给调用者'''
return MyNumber(lhs - self.data)
n1 = MyNumber(100)
n2 = MyNumber(200)
n3 = n1 - 200 # 等同于n1.__sub__(200)
# n3 = n1.__sub__(200)
print(n1, "-200", '=', n3)
n4 = 600 - n2 # 等同于n2.__rsub__(600)
#n4 = n2.__rsub__(600)
print('n4 =', n4)
其它复合赋值算术运算符也具有相同的规则
复合赋值算术运算重载
方法名 运算符和表达式 说明说明
a、如果__add__和__iadd__的方法不同(运算结果不同)的时候,x += x 和 x = x + x是不等价的,两者得到的结果是不同的,其他复合运算同理
b、如果__add__和__iadd__同时存在,复合运行优先采用__iadd__方法
c、如果__iadd__不存在,复合运行采用__add__方法
d、如果__add__和__iadd__均存在,运行报错
示例
# 此示例示意复合赋值算术运算符的重载
class YouList:
def __init__(self, iterable):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __add__(self, rhs):
print("__add__方法被调用")
return YouList(self.data + rhs.data)
class MyList:
def __init__(self, iterable):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __add__(self, rhs):
print("__add__方法被调用")
return MyList(self.data + rhs.data)
def __iadd__(self, rhs):
print("__iadd__方法被调用")
self.data.extend(rhs.data)
return self
L1 = MyList([100])
L1 += L1 # __iadd__方法被调用
print('L1 =', L1)
L2 = YouList([100])
L2 += L2 # __add__方法被调用
print('L2 =', L2)
__rshift__(self, rhs) self >> rhs 右移
反向位运算符的重载
方法名 运算符和表达式 说明__rrshift__(self, lhs) lhs >> self 右移
复合赋值位运算符的重载
方法名 运算符和表达式 说明__irshift__(self, rhs) self >>= rhs 右移
__invert__(self) ~ self 取反
重载方法
def __xxx__(self):...
示例
# 此示例示意一元运算符的重载
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __neg__(self):
'''规则是正变负,负变正'''
L = (-x for x in self.data)
return MyList(L)
L1 = MyList([1, -2, 3, -4, 5])
L2 = -L1 # 等同于L1.__neg__()
print(L2)
in / not in 运算符
方法名 运算符和表达式 说明__contains__(self, e) e in self 成员运算
示例
# 此示例示意一元运算符的重载
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __contains__(self, e):
return e in self.data
L1 = MyList([1, -2, 3, -4, 5])
if 3 in L1:
print("3 在 L1内")
if 4 not in L1:
print('4 不在L1内')
__delitem__(self, i) del self[i] del语句索引/切片
作用
让自定义的类型的对象能够支持索引和切片操作
示例
# 此示例示意[]运算符的重载
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __getitem__(self, i):
# print("i =", i)
return self.data[i]
def __setitem__(self, i, val):
self.data[i] = val
def __delitem__(self, i):
del self.data[i]
L1 = MyList([1, -2, 3, -4, 5])
x = L1[0] # L1.__getitem__(0)
print(x)
L1[1] = 2 # L1.__setitem__(1, 2)
print(L1)
print(L1[0:5:1]) # 切片读取列表
L1[::] = [] # 删除 列表中值
print(L1)
用于创建一个slice切片对象,此对象存储一个切片起始值,终止值,步长值信
格式
slice(start=None, stop=None, step=None) 创建 一个slice 切片对象s.step 要片的步长
示例
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __getitem__(self, i):
print("i =", i)
if type(i) is slice:
print("您正在执行切片取值操作")
print("起始值是:", i.start)
print("终止值是:", i.stop)
print("步长是:", i.step)
return self.data[i]
L1 = MyList([1, -2, 3, -4, 5])
x = L1[1:8:2]
print(x) #
实现其它语言所拥有的 getter 和 setter功能(实现魔法函数)
作用
a、用来模拟一个属性b、通过@property装饰器可以对模拟的属性赋值和取值加以控制
示例
# 此示例示意特性属性的用法
class Student:
def __init__(self, score):
self.__score = score
def get_score(self):
'''实现getter'''
return self.__score
def set_score(self, s):
'''实现setter'''
print("正在调用setter")
if 0 <= s <= 100:
self.__score = s
else:
raise ValueError
score = property(get_score, set_score)
s = Student(59)
print(s.score) # print(s.get_score())
s.score = 97 # s.set_score(97)
print(s.score) # ...
# 此示例示意特性属性的用法
class Student:
def __init__(self, score):
self.__score = score
@property
def score(self): # score = propery(score)
'''实现getter'''
return self.__score
@score.setter
def score(self, s):
'''实现setter'''
print("正在调用setter")
if 0 <= s <= 100:
self.__score = s
else:
raise ValueError
s = Student(59)
print(s.score) # print(s.get_score())
s.score = 97 # s.set_score(97)
print(s.score) # ...
人工智能(python)—— 目录汇总