完整代码请查看github项目: advance-python
前言
特殊方法是为我们定义的类添加上某些特殊功能的方法,上一讲分组讲解了Python的几对特殊方法(或者成为魔术方法),分别是,__new__与__init__
__enter__与__exit__
__str__与__repr__
__setattr__、__getattr__、__getattribute__与__delattr__
这些都是相对较为常用的。Python中类的特殊方法远不止这些,其中还有一些不太常用,或者在某些特定场景下用到的特殊方法。
本讲会按照功能对剩余的特殊方法进行分类,不再详细的把每个特殊方法的使用都展开阐述,会着重的从每种功能中挑选出具有代表性的特殊方法进行实现、详细讲解。
函数调用
假如我们定义一个用于算数运算的类,
class Operation(object):
def __init__(self, x, y):
self.x = x
self.y = y
def add(self):
print("The result is {}".format(self.x + self.y))
opt = Operation(2, 2)
opt.add()
# 输出
The result is 4
从这段代码可以看出 ,这是我们一贯使用类及类方法的方式,实例化--调用,其实Python提供有特殊方法__call__能够让类的调用像调用函数的方式一样。
这句话听着似乎很绕口,具体什么含义呢?用一段代码来说明,
class Operation(object):
def __init__(self):
self.x = None
self.y = None
def add(self):
print("The result is {}".format(self.x + self.y))
def __call__(self, x, y):
self.x = x
self.y = y
self.add()
opt = Operation()
opt(3, 3)
# 输出
The result is 6
当我们给类添加特殊方法__call__后,我们可以直接使用实例名(opt)来调用类的方法,就不用在用instance.method的方法去调用。换句话说就是,当我们定义__call__后,我们使用实例名进行调用时,它会首先进入__call__方法,执行__call__中的程序。
容器与序列
容器和序列分别涉及2个特殊方法:__contains__、__len__。
从__len__名称就可以看出它的功能,给类添加一个获取序列长度的功能,所以这里着重讲解一下容器,顺带讲解一下__len__。
我们在条件语句中经常会用到这样的语句if ... in、if ... not in,其中__contains__就可以给类添加这样一个功能,可以通过if ... in、if ... not in来调用类的实例,以一段代码来举例,
class Contain(object):
def __init__(self, data):
self.data = data
def __contains__(self, x):
return x in self.data
def __len__(self):
return len(self.data)
contain = Contain([2,3,4,5])
if 2 in contain:
print("222222")
if 6 not in contain:
print("666666")
len(contain)
# 输出
222222
666666
4
从代码中可以看出,当我们调用if 2 in contain时会调用__contains__这个特殊方法,通过方法中的语句返回一个布尔型的值。
此外,可以看到代码中有这样一句调用len(contain),它就是前面提到的特殊方法__len__的功能,它可以给类添加一个获取序列长度的功能,当使用len(instance)时会调用__len__方法中的程序。
算数运算
用于实现算数运算的有以下类的特殊方法的有以下几个,
以一段代码举例说名加法与乘法的使用,
class Operation(object):
def __init__(self, value):
self.value = value
def __add__(self, other):
return Operation(self.value + other.value)
def __mul__(self, other):
return Operation(self.value * other.value)
def __str__(self):
return "the value if {}".format(self.value)
a = Operation(3)
b = Operation(5)
print(a + b)
print(a * b)
# 输出
the value if 8
the value if 15
同理,其他几种算法运算的使用方法同加法、乘法相同。
比较运算
类的特殊方法不仅提供了算术运算,还提供了比较运算的特殊方法,它们分别是,
以一段代码解释比较运算符的使用,
class Cmp(object):
def __init__(self, value):
self.value = value
def __eq__(self, other):
return self.value == other.value
def __gt__(self, other):
return self.value > other.value
a = Cmp(3)
b = Cmp(3)
a == b
# 输出
True
可以看出,比较运算和算术运算的使用非常相似。
字典功能
我们可以通过如下几个特殊方法为类添加如同字典一样的功能,
下面以一段代码举例说明,
class Dictionaries(object):
def __setitem__(self, key, value):
self.__dict__[key] = value
def __getitem__(self, key):
return self.__dict__[key]
def __delitem__(self, key):
del self.__dict__[key]
diction = Dictionaries()
diction["one"] = 1
diction["two"] = 2
diction["three"] = 3
diction['three']
del diction['three']
diction['three']
# 输出
3
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
in ()
----> 1 diction['three']
in __getitem__(self, key)
4
5 def __getitem__(self, key):
----> 6 return self.__dict__[key]
7
8 def __delitem__(self, key):
KeyError: 'three'
可以看出,当删除键值为three的值之后再次去获取会报错。
其他
除了上述提到的特殊方法之后,Python还有很多特殊方法,这里不一一举例说明,下面列举出这些特殊方法以及它们的功能和使用方法,如果感兴趣的可以对应的去查找文档学习。
当然,除了这些,Python还有其他的特殊方法,例如逻辑运算、按位运算等,感兴趣的可以参考官方文档仔细学习一下,本文仅列举一些相对常用的一些特殊方法。
文档获取
本讲的Markdown格式文档我进行共享了,需要的可以关注公众号【平凡而诗意】回复关键字"python"获取。
推荐
如果希望更加深入的学习Python,我建议还是应该选择一本不错的书籍从头至尾好好学习一遍,因为很多课程或者博客难免会有不严谨之处,而书籍中会更加严谨详细,能够涉及到很多平日里容易忽略的点,这里我推荐三本书籍,其中一本是用于入门,另外两本适合进阶,
入门书籍-《Python编程 从入门到实践》
进阶书籍-《流畅的Python》
进阶书籍-《Python CookBook》
当然,书籍没必要每一本都看完,选择其中适合自己的一本认真学习一遍即可。
干货
最近,为了方便大家,我花费了半个月的时间把这几年来收集的各种技术干货整理到一起,其中内容包括但不限于Python、机器学习、深度学习、计算机视觉、推荐系统、Linux、工程化、Java,内容多达5T+,我把各个资源下载链接整理到一个文档内,目录如下:
所有干货送给大家,希望能够点赞支持一下!
往期内容Jackpop:目录 | 精选CV、Python等系列教程zhuanlan.zhihu.com