Python基础——魔法方法

Posted 薛定谔的猫ovo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python基础——魔法方法相关的知识,希望对你有一定的参考价值。

文章目录


描述符(Property的原理)

所谓描述符(descriptor) 就是将某种特殊类型的类的实例指派给另一个类的属性
那什么是特殊类型的类呢?就是至少要在这个类里边定义_ _get_ _()、_ _set_ _()或_ _delete_ _()三个特殊方法中的任意一个。

下表列举了描述符相关的魔法方法。

魔法方法含义
_ _get_ _(self, instance, owner)用于访问属性,它返回属性的值
_ _set_ _(self, instance, value)将在属性分配操作中调用,不返回任何内容
_ _delete_ _(self, instance)控制删除操作,不返回任何内容

举个简单的例子:

由于MyDescriptor实现了_ _get_ _()、_ _set_ _()和_ _delete_ _()方法,并将它的类实例指派给Test类的属性,所以MyDescriptor就是所谓描述符类

1、_ _get_ _()方法

当访问x属性的时候,Python会自动调用描述符的_ _get_ _()方法,几个参数的内容分别是:self是描述符自身的实例;instance是这个描述符的拥有者所在的类的实例,在这里也就是Test类的实例;owner是这个描述符的拥有者所在的类本身。

2、_ _set_ _()方法

对x属性进行赋值操作的时候,Python会自动调用_ _set_ _()方法,前两个参数跟_ _get_ _()方法是一样的,最后一个参数value是等号右边的值。

3、最后一个del操作也是同样的道理:



只要弄清楚描述符,那么property就不再是秘密了。property实际上就是一个描述符类。下面定义一个属于我们自己的MyProperty:



定制序列

本节要谈论的是定制容器,要向成功的实现容器的定制,便需要先谈一谈协议
所谓协议(Protocol),其与其他编程语言中的接口很相似,它规定哪些方法必须要定义。在Python中协议并没有那么正式,事实上,在Python中,协议更像是一种指南。

在Python中,像 序列类型(例如元组、列表、字符串)映射类型(如字典) 都是属于容器类型。要定制容器,就要先知道定制容器有关的一些协议

  • 如果你希望定制的容器是不可变的话,你只需要定义_ _len_ _()和_ _getitem_ _()方法。
  • 如果你希望定制的容器是可变的话,除了_ _len_ _()和_ _getitem_ _()方法,你还需要定义_ _setitem_ _()和_ _delitem_ _()两个方法。

下表列举了定制容器类型相关的魔法方法及含义:

魔法方法含义
_ _len_ _(self)定义当被len()函数调用时的行为(返回容器中元素的个数)
_ _getitem_ _(self, key)定义获取容器中指定元素的行为,相当于self[key]
_ _setitem_ _(self, key, item)定义设置容器中指定元素的行为,相当于self[key] = value
_ _delitem_ _(self, key)定义删除容器中指定元素的行为,相当于del self[key]
_ _iter_ _(self)定义当迭代容器中的元素的行为
_ _reversed_ _(self)定义当被reversed()函数调用时的行为
_ _contains_ _(self, item)定义当使用成员测试运算符(in或not in)时的行为

举个例子,定义一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数:




迭代器

迭代相信大家已经遇到过很多次了,迭代的意思类似于循环,每一次重复的过程被称为一次迭代的过程,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。

提供迭代方法的容器称为迭代器,通常接触的迭代器有序列(列表、元组、字符串)还有字典,它们都支持迭代的操作。

举个例子,通常使用for循环语句来进行迭代:

字符串就是一个容器,同时也是一个迭代器,for循环语句的作用就是触发这个迭代器的迭代功能,每次从容器中依次拿出一个数据,这就是迭代操作。同样,字典和文件也是支持迭代操作的。

关于迭代,Python提供了两个BIF:

  • iter()
  • next()

对于一个容器对象,调用 iter() 就得到它的迭代器,调用 next() 迭代器就会返回下一个值,然后怎么结束呢?如果迭代器没有值可以返回了,就会抛出一个叫做StopIteration的异常:


那么关于实现迭代器的魔法方法有两个:

  • _ _iter_ _()
  • _ _next_ _()

一个容器如果是迭代器,就必须要实现_ _iter_ _()魔法方法,这个方法实际上就是返回迭代器本身。接下来重点要实现的是_ _next_ _()魔法方法,因为它决定了迭代的规则。

举个简单的例子:

以上是关于Python基础——魔法方法的主要内容,如果未能解决你的问题,请参考以下文章

Python基础——魔法方法

Python基础——魔法方法

Python 魔法方法

Python学习————魔法方法

Python学习之路——Python基础之基本数据类型

Python学习之路——Python基础之基本数据类型