本章重点内容:
1、基础知识
2、索引和分片:__getitem__和__setitem__
3、索引迭代:__getitem__
4、可迭代对象:__iter__和__next__
5、属性访问:__getattr__和__setattr__
6、字符串显示:__repr__和__str__
7、右侧加法和原位置加法:__radd__和__iadd__
8、调用表达式:__call__
9、比较运算:__lt__、__gt__和其他方法
10、布尔测试:__bool__和__len__
11、对象析构函数:__del__
接下来针对以上内容进行详细的说明,如下:
1、基础知识
运算符重载,意味着在某个类的方法中拦截内置的操作,当类的实例出现在内置操作中时,Python会自动调用你的方法,并且你的方法的返回值会作为相应操作的结果,
1)运算符重载让类拦截常规的Python操作
2)类可重载所有Python表达式运算符
3)类也可重载打印、函数调用、属性访问等内置运算
4)重载使类实例的行为更接近内置类型
5)重载是通过在一个类中提供特殊名称的方法来实现的
我们通过一个简单的例子来看下构造函数(__init__)和表达式(__sub__)的运算符重载,来理解上面的内容,具体代码如下:
常见的运算符重载方法还有很多,接下来择取重点且常见的说明,至于有哪些或者多少运算符重载方法,可以百度查看,书上列表中,已经列明了至少27类,其他的应该还有
2、索引和分片:__getitem__和__setitem__
我们先来看索引和分片的运算符重载,当实例X出现在X[i]这样的索引运算中时,Python会调用这个实例继承的__getitem__方法,把X作为第一位参数传入,并且将方括号内的索引值传递给第二个参数,具体代码如下:
__getitem__是查看类属性的值,可以通过索引,而__setitem__是更新类属性的值,主要是针对有键值对的,具体代码实例如下:
3、索引迭代:__getitem__
也就是说,如果有该方法存在,那该类的对象,是可迭代的,例如,承接上面的例子,可以通过list()函数直接查看实例X中的内容
在这里是一个概念或者说技巧,后续在使用中可考虑
4、可迭代对象:__iter__和__next__
虽然上面说的__getitem__可用,但是Python中所有的迭代上下文都会先尝试__iter__方法,再尝试__getitem__,也就是说我们应该优先调整__iter__方法
通过__iter__和__next__方法的结合使用,可以实现类实例的迭代,具体代码如下:
以上是创建了一个类,接下来通过实例来使用迭代功能
5、属性访问:__getattr__和__setattr__
__getattr__是访问属性,__setattr__是修改属性
先创建一个简单的类,如果要访问不存在的属性,系统会出现提示信息,具体代码如下:
对于类,如果你直接添加属性和值是可以的,但是可以通过__setattr__来屏蔽,还是承接上面代码的实例,代码调整如下:
对于以上代码,运行结果如下:
6、字符串显示:__repr__和__str__
关于字符串显示,前面章节中有说明,也有用到__repr__来设计打印类的结果,那与__str__有什么区别呢?
__str__:会首先被打印操作和str内置函数尝试(print运行的内部等价形式),它通常应当返回一个用户友好的显示
__repr__:用于所有其他的场景,如果没有定义__str__则打印操作也会使用__repr__,也就是说可以用于任何地方
通过以下代码,会更好的说明这一点:
首先,看下,如果没有定义__str__和__repr__的情况下会是什么情况
你会发现,直接调用实例或者打印实例,都是显示一串代码,它是说明该实例的内存地址
如果先定义__repr__,看下结果:
再定义__str__看下结果:
7、右侧加法和原位置加法:__radd__和__iadd__
常规定义的__add__一般都是右侧加法,也就是相加的对象在实例的右侧,如果是左侧,系统会提示错误,具体代码示例如下:
通过定义__radd__来解决这个问题
如果要实现【+=】这种原位置加法,可以通过__iadd__来定义,具体代码示例如下:
8、调用表达式:__call__
通过定义__call__可以实现实例不同的调用,具体代码如下:
9、比较运算:__lt__、__gt__和其他方法
这个比较容易理解,就是如果实例与其他比较时,如何处理,具体代码说明如下:
10、布尔测试:__bool__和__len__
Python会首先尝试__bool__来获取一个直接的布尔值,如果没有该方法,就退而求其次的尝试__len__来根据对象的长度确定真值,
系统默认实例对象是真的,如果需要我们特殊的处理,可以通过这个定义不一样的结果,
先看系统默认的情况:
定义新的结果:
11、对象析构函数:__del__
我们知道实例创建的时候会调用__init__来创建,如果实例空间被回收时,就会调用__del__,一般来说,系统是自动调用完成的,在此我们可以了解这个如何运作的,析构函数一般不常用,但是很重要
具体代码示例如下:
本文为作者手打原创,如有引用请取得作者同意
说明:本章内容基于《Python学习手册 第五版》内容学习整理