上一章,我们使用Animal和Dog的例子讲解了什么是继承,其中Dog中eat函数实现了对Animal中eat函数的重写。除了这种自定义函数的重写,在本章中,我们还会介绍一些特殊的函数重写(重载)。
一、基础重载方法
一些基础的类方法,如构造函数“__init__”、析构函数“__del__”,在前面的内容我们已经讲过如何进行重载,例如继承时对构造函数的重载,按需求销毁对象时自定义的析构函数。
除此外,还有其他的一些基础类方法,可以实现重载,此处举出几个代表,其中obj代表由类生成的对象:
方法/函数名 | 触发时机/调用方法 | 用途说明 |
__init__ | 创建对象时 | 初始化对象 |
__del__ | del obj | 销毁对象 |
__str__ | str(obj) | 获取对象的字符串表示 |
__len__ | len(obj) | 获取对象的长度 |
__contains__ | x in obj | 对象里是否包含某个成员 |
__call__ | obj() | 让对象能够像函数一样被调用 |
__iter__ | for x in obj | 迭代器 |
__getitem__ | obj[key] | 索引访问,如列表、字典 |
__setitem__ | obj[key] = value | 索引赋值 |
在重写的基础类方法中,我们可以实现一些自定义的代码逻辑。例如对于前面的Dog类,我们创建一个dog对象,并使用str去对其进行字符串表示,得到的结果是:
dog = Dog("金毛", "黄色")print(str(dog))# Output: <__main__.Dog object at 0x10be18710>
会发现,输出内容是程序内部的一些控制量,没有太多实际含义。如果在Dog类中重载str,再进行输出,则可以让结果多样化:
class Dog:def __str__(self):return f"这是一只{self.hair_color}的{self.breed}。"dog = Dog("金毛", "黄色")print(str(dog))# Output: 这是一只黄色的金毛。
除此外,对于如“__getitem__”、“__contains__”等类方法,为了实现其预期效果,我们还需要添加如index、key、value等辅助的形参,帮助函数实现内部逻辑。
在重写“__iter__”时,我们通常使用“yield”关键词来替代“return”实现内容的迭代返回。yield将函数变成生成器(Generator),调用时不会立即执行,而是返回一个生成器对象;每次迭代时,函数从上次暂停的地方继续运行,直到再次遇到yield。不正确地说,yield就是返回了一系列值构成的列表。
def count_down(n):while n > 0:yield nn -= 1for i in count_down(3):print(i, end=" ")# Output: 3 2 1
二、运算符重载
除基础的一些类方法重载,Python也支持对运算符进行重载:
方法/函数名 | 触发时机/调用方法 | 用途说明 |
__eq__ / __ne__ | obj == other_obj obj != other_obj | 等于或不等于比较 |
__lt__ / __le__ | obj <= other_obj obj < other_obj | 小于或小于等于 |
__gt__ / __ge__ | obj >= other_obj obj > other_obj | 大于或大于等于 |
__add__ / __sub__ | obj + other_obj obj – other_obj | 加减运算 |
__mul__ / __truediv__ | obj * other_obj obj / other_obj | 乘除运算 |
举例,我们定义一个虚数类,并重载运算方法:
class Complex:def __init__(self, real: float, imag: float):self.real = realself.imag = imagdef __str__(self) -> str:return f"{self.real} + {self.imag}i"def __add__(self, other):return Complex(self.real + other.real, self.imag + other.imag)def __sub__(self, other):return Complex(self.real - other.real, self.imag - other.imag)def __mul__(self, other):return Complex(self.real * other.real - self.imag * other.imag,self.real * other.imag + self.imag * other.real)
然后,我们调用几个运算:
c1 = Complex(1, 2)c2 = Complex(3, 4)print(f"c1 = {c1}") # Outout: c1 = 1 + 2iprint(f"c2 = {c2}") # Output: c2 = 3 + 4iprint(f"c1 + c2 = {c1 + c2}") # Output: c1 + c2 = 4 + 6iprint(f"c1 - c2 = {c1 - c2}") # Output: c1 - c2 = -2 + -2iprint(f"c1 * c2 = {c1 * c2}") # Output: c1 * c2 = -5 + 10i
通过运算示例发现,其按照我们定义好的正常虚数计算逻辑完成了运算。此处还要注意,我们用格式化字符串输出,并没有显式调用str重载,但是解释器会自动进行调用。
往期回顾:
用PyEcharts画些炫酷图表|PyEcharts教程Part.11