第47讲:魔方方法——定制序列

一 协议的相关概念

1 定义:协议(protocols)与其他编程语言中的接口很相似,它规定你哪些地方必须要定义哪些东西。在python中,协议更像是一种指南

可参考:https://www.cnblogs.com/allen2333/p/8862341.html

二 容器类型的协议

__len__(self) 定义当被 len() 调用时的行为(返回容器中元素的个数)
__getitem__(self, key) 定义获取容器中指定元素的行为,相当于 self[key]
__setitem__(self, key, value) 定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key) 定义删除容器中指定元素的行为,相当于 del self[key]
__iter__(self) 定义当迭代容器中的元素的行为
__reversed__(self) 定义当被 reversed() 调用时的行为
__contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为

注意:

  • 如果希望定制的容器是不可变的话,只需要定义__len__()和__getitem__()方法
  • 如果希望定制的容器是可变的话,除了__len__()和__getitem__()方法,还需要定义__setitem__()和__delitem__()两个方法。

三 练习要求

  • 编写一个不可变的自定义列表,要求记录列表中每个元素被访问的次数
  • 代码:
     1 class CountList(object):
     2     def __init__(self,*args):
     3         self.values = [x for x in args]
     4         self.count = {}.fromkeys(range(len(self.values)),0)
     5         print(self.count)
     6     
     7     def __len__(self):
     8         return len(self.values)
     9     
    10     def __getitem__(self,key):
    11         self.count[key] += 1
    12         print(self.count)
    13         return self.values[key]
  • 涉及知识:

 四 课后作业

测试题部分:

0. 你知道 Python 基于序列的三大容器类指的是什么吗?
答:无疑是列表(List),元组(Tuple)和字符串(String)啦。

1. Python 允许我们自己定制容器,如果你想要定制一个不可变的容器(像 String),你就不能定义什么方法?
答:如果你想要定制一个不可变的容器(像 String),你就不能定义像 __setitem__() 和 __delitem__() 这些会修改容器中的数据的方法。

2. 如果希望定制的容器支持 reversed() 内置函数,那么你应该定义什么方法?
答:应该定义 __reversed__() 方法,提供对内置函数 reversed() 的支持。

3. 既然是容器,必然要提供能够查询“容量”的方法,那么请问需要定义什么方法呢?
答:在 Python 中,我们通过 len() 内置函数来查询容器的“容量”,所以容器应该定义 __len__() 方法。

4. 通过定义哪些方法使得容器支持读、写和删除的操作?
答:读 —— __getitem__(),写 —— __setitem__(),删除 —— __delitem__(),

5. 为什么小甲鱼说“在 Python 中的协议就显得不那么正式”?
答:在 Python 中,协议更像是一种指南。这有点像我们之前在课后作业中提到的“鸭子类型”(忘了的朋友请戳:http://bbs.fishc.com/thread-51471-1-1.html) —— 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。Python就是这样,并不会严格地要求你一定要怎样去做,而是让你靠着自觉和经验把事情做好!

原文地址:https://www.cnblogs.com/luoxun/p/13688510.html