python面向对象编程最大的乐趣在于“函数重写”,是得我们自定的对象,可以像python内建对象一样,进行函数操作。
一. 函数重写 overwrite
- 什么是函数重写:在自定义的类内添加相应的特殊方法,让自定义的类生成的对象(实例)像内建对象一样进行函数操作。
二. 对象转字符串的重写方法
- 对象转字符串函数:repr && str
- repr(x):返回一个能代表此对象的表达式字符串,通常eval(repr(obj)) = obj;
- str(obj):通过给定对象返回一个字符串(这个字符串通常是给人阅读的);
- eval(str):将字符串当成表达式来运行
- 对象转字符串的重写方法:(类似于java中重写toString()方法)
- repr()函数的重写方法
def __repr__(self):
...
return 字符串 # 返回的对象必须是字符串
2. str()函数的重写方法:
def __str__(self):
...
return 字符串 # 返回的对象必须是字符串
3. str(obj) 函数调用方法说明:
- str(obj) 函数先查找obj.__str__()调用此方法,并返回结果
- 如果obj.__str__这个方法不存在,则调用obj.__repr__()方法并返回结果;
- 如果obj.__repr__()方法不存在,则调用object类的__repr__实例方法打印<__main__.MyNumber object at xxx>
"""对象转字符串的重写方法"""
class MyNumber:
def __init__(self, value):
self.data = value
def __str__(self):
"""此方法继承自父类object"""
return "自定义数据MyNumber(%d)" % self.data
def __repr__(self):
return 'MyNumber(%d)' % self.data
if __name__ == "__main__":
print(MyNumber(100))
print(MyNumber(100).__str__())
print(str(MyNumber(100)))
print(repr(MyNumber(200)))
print(MyNumber(200).__repr__())
print(eval(repr(MyNumber(300))))
运行结果:
三. 内建函数重写
重写方法 | 调用 |
__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 __str__(self):
return '%d' % self.data
def __abs__(self):
"""此方法用于制定abs(obj)函数取值时返回的结果"""
if self.data < 0:
return MyInteger(-self.data)
return MyInteger(self.data)
def __len__(self):
return len(self.__abs__().__str__())
def __reversed__(self):
return MyInteger(self.data * -1)
print(MyInteger.__mro__)
num = MyInteger(-100)
# 等同于print(str(i1))
print("自定义的整数:{}".format(num))
# dir(object)没有__abs__方法
print("{}的绝对值为{}".format(repr(num), abs(num)))
print("{}的长度为{}".format(repr(num), len(num)))
print("{}反转后为{}".format(repr(num), repr(reversed(num))))
运行结果:
四. 数值转换函数重写
重写方法 | 函数调用 |
__complex__ | complex(obj) |
__int__ | int(obj) |
__float__ | float(obj) |
__bool__ | bool(obj) |
- 布尔测试函数重写
- 格式:def __bool__(self):
- 作用:bool(obj)函数取值 | if语句真值表达式 | while语句的值表达式
- 说明:
- 当自定义类内有__bool__(self)方法时,以此方法的返回值作为bool(obj)的返回值;
- 当不存在__bool__(self)方法时,根据__len__(self)方法的返回值是否为0来测试bool值;
- 当再不存在__len__(self)方法时,返回True;
class MyList:
"""__bool__方法的重写方法及用法"""
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
print('__repr__方法被调用')
return 'MyList(%s)' % self.data
def __len__(self):
print('__len__方法被调用')
return len(self.data)
def __bool__(self):
"""此方法用来制定一个bool(x)返回的规则"""
print("__bool__方法被调用")
if len(self.data) == 0:
return False
for x in self.data:
if x:
return True
return False
if __name__ == "__main__":
myl = MyList([1, -2, 3, -4])
print("my1:{}, {}".format(myl, bool(myl)))
my2 = MyList([0, 0.0, False])
print("my2:{}, {}".format(my2, bool(my2)))
运行结果1:
运行结果2:注释掉__bool__运行
运行结果3:注释掉__bool__和__len__方法运行
五. 自定义类实现迭代器功能
- 什么是迭代器:可以通过next函数取值的对象称为迭代器;
- 迭代器协议:对象能够使用next函数获取下一个数据,在没有下一项数据时触发一个Stopiteration异常来终止迭代的约定;
- 迭代器的实现办法:__next__(self) 方法用来实现迭代器协议;
- 什么是可迭代对象:是指能用iter(obj)返回迭代器对象,可迭代对象内部要定义__iter__(self)来返回迭代器对象;
- 可迭代对象的语法形式:
class MyIterable:
def __iter__(self):
语句块
return 迭代器
示例:
class MyIterator:
"""用自定义的类MyIterator实现迭代器"""
def __init__(self, start, stop, step):
# 用来记录迭代器的起始位置和当前位置
self.start = start
self.stop = stop
self.step = step
def __next__(self):
"""实现迭代器协议"""
if self.start >= self.stop:
raise StopIteration
# 将要返回的数据存入一个变量
r = self.start
self.start += self.step # 迭代器后移
return r
class MyRange:
"""使用自定义的类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类型创建的对象当做可迭代对象"""
# 返回值必须为一个迭代器
return MyIterator(self.start, self.stop, self.step)
if __name__ == "__main__":
L = [x for x in MyRange(5)]
print(L)
R = iter(MyRange(1, 6, 2))
while True:
try:
print(next(R))
except StopIteration:
break
运行结果: