python高级(一)—— python数据模型(特殊方法)
本文主要内容
collections.namedtuple
__getitem__ 和 __len__
__repr__和__str__
__abs__、__add__和__mul__
__bool__
文中代码均放在github上:https://github.com/ampeeg/cnblogs/tree/master/python高级
本文内容的表格式总结
| 语 法 | 调用的方法(按照顺序寻找) | 备注 |
| list[2] | __getitem__(2) | |
| list[1:3:2] | __getitem__(slice(1,3,2)) | 切片时传入的参数是slice类型 |
| for i in object: | __iter__()、__getitem__() | __iter__需要返回迭代器,并不断调用next() |
| in object | __contains__()、__iter__()、__getitem__() | __iter__()、__getitem__()会按照顺序搜索 |
| print(object) | __str__()、__repr__() | |
| if object: | __bool__()、__len__() |
使用if、while等判断句时,会调用__bool__() 如果没有这两个方法,一般情况下,自定义的类总认为是真的 |
何为python的数据模型
本文所指的python数据模型,也可成为python中内置的对象模型(一切皆为对象),其包含的一些方法为特殊方法,在java中也称“魔术方法”。由于python文档里面喜欢使用“数据模型”这个词,所以本文依此称数据模型。
简单来说,数据模型就是python自有的数据类型,及其包含的特殊方法。例如:使用len()时会调用__len__特殊方法;使用list[]时会调用__getitem__方法;使用各类运算符也会调用其相对应的方法。从根本上而言,list[]、+、-、*、/、for i in x这些写法只是为了更简洁和更具有可读性,但内部跟其他操作一下,也是通过方法实现的,这就是特殊方法。
可命名元组(namedtuple)
# 导入可命名元组 |
__getitem__ 和 __len__
1、__len__
class Foo: |
2、__getitem__
from collections import namedtuple
Stock = namedtuple("stock", ["name", "price"])
class Foo:
|
重写__getitem__后就可直接遍历对象:
if __name__ == "__main__": |
3、继续说说for i in x: 语句
刚刚我们使用for i in foo时发现可以正常迭代,如果在Foo类中重写__iter__方法,则无法正确迭代了:
from collections import namedtuple
Stock = namedtuple("stock", ["name", "price"])
class Foo:
|
如果我们把以上__iter__方法改成如下,那么又可使用for语句了:
def __iter__(self):
return iter(self._stock)
事实上我们在使用for i in foo语句时,会先调用__iter__方法,返回一个迭代器,然后for循环会不断使用next()进行遍历;如果foo里面没有该方法,则会调用__getitem__,并会从0开始依次读取相应的下标,直到发生IndexError为止,这是一种旧的迭代协议。
同样的,使用in判断时,解释器会依次寻找__contains__、__iter__、__getitem__方法。
from collections import namedtuple
Stock = namedtuple("stock", ["name", "price"])
class Foo:
|
__repr__和__str__
# 接下来的例子引用自《流畅的python》 |
__abs__、__add__和__mul__
# 接上面的二维向量的例子
from math import hypot
class Vector:
def __init__(self, x=0, y=0):
|
__bool__
# 继续在上面列子中添加__bool__
from math import hypot
class Vector:
def __init__(self, x=0, y=0):
|
python中的全部特殊方法
本部分内容可以参考官方网站 https://docs.python.org/3/reference/datamodel.html#special-method-names
python中一共有83个特殊方法,其中47个用于算术运算、位运算和比较操作。我根据《流畅的python》中的整理,摘录如下两个表格
表1:跟运算符无关的特殊方法
| 类 别 | 方法名 |
| 字符串/字节序列表示形式 | __repr__、__str__、__format__、__bytes__ |
| 数值转换 | __abs__、__bool__、__complex__、__int__、__float__、__hash__、__index__ |
| 集合模拟 | __len__、__getitem__、__setitem__、__delitem__、__contains__ |
| 迭代枚举 | __iter__、__reversed__、__next__ |
| 可调用模拟 | __call__ |
| 上下文管理 | __enter__、__exit__ |
| 实例创建和销毁 | __new__、__init__、__del__ |
| 属性管理 | __getattr__、__getattribute__、__setattr__、__delattr__、__dir__ |
| 属性描述符 | __get__、__set__、__delete__ |
| 跟类相关的服务 | __prepare__、__instancecheck__、__subclasscheck__ |
表2:跟运算符相关的特殊方法
| 类 别 | 方法名和对应的运算符 |
| 一元运算符 | __neg__ -、__pos__ +、__abs__ abs() |
| 众多比较运算符 | __lt__ <、__le__ <=、__eq__ ==、__ne__ !=、__gt__ >、__ge__>= |
| 算数运算符 |
__add__ +、__sub__ -、__mul__ *、__truediv__ /、__floordiv__ //、 __mod__ %、__divmod__ divmod()、__pow__ **或pow()、__round__ round() |
| 反向算数运算符 | __radd__、__rsub__、__rmul__、__rtruediv__、__rfloordiv__、__rmod__、__rdivmod__、__rpow__ |
| 增量赋值算术运算符 | __iadd__、__isub__、__imul__、__itruediv__、__ifloordiv__、__imod__、__ipow__ |
| 位运算符 | __invert__ ~、__lshift__ <<、__rshift__ >>、__and__ &、__or__ |、__xor__ ^ |
| 反向位运算符 | __rlshift__、__rrshift__、__rand__、__rxor__、__ror__ |
| 增量赋值位运算符 | __ilshift__、__irshift__、__iand__、__ixor__、__ior__ |
如何使用特殊方法:
1、特殊方法的调用是隐式的,通常你的代码无需直接使用特殊方法。除非有大量的元编程存在,直接调用特殊方法的频率应该远远低于你去实现它们的次数。唯一的例外可能是__init__方法,你的代码里可能经常会用到它,目的是在你的子类的__init__方法中调用超类的构造器。
2、通过内置的函数(例如len、iter、str等)来使用特殊方法是最好的选择。这些内置函数不仅会调用特殊方法,通常还提供额外的好处,而且对于内置的类来说,它们的速度更快。
3、不要自己想当然地随意添加特殊方法,比如__foo__之类的,因为虽然现在这个名字没有被python内部使用,以后就不一定了。
——《流畅的Python》
python高级系列文章目录
python高级(一)—— python数据模型(特殊方法)的更多相关文章
- Python高级编程-Python一切皆对象
Python高级编程-Python一切皆对象 Python3高级核心技术97讲 笔记 1. Python一切皆对象 1.1 函数和类也是对象,属于Python的一等公民 ""&qu ...
- 第九章:Python高级编程-Python socket编程
第九章:Python高级编程-Python socket编程 Python3高级核心技术97讲 笔记 9.1 弄懂HTTP.Socket.TCP这几个概念 Socket为我们封装好了协议 9.2 cl ...
- 为什么用Python,高级的Python是一种高级编程语言
Python特性 如果有人问我Python最大的特点是什么,我会毫不犹豫地告诉他:它简单易学,功能强大.作为一个纯自由软件,Python有许多优点: 很简单.基于"优雅".&quo ...
- Python高级编程技巧(转)
译文:http://blog.jobbole.com/61171/ 本文展示一些高级的Python设计结构和它们的使用方法.在日常工作中,你可以根据需要选择合适的数据结构,例如对快速查找性的要求.对数 ...
- python高级——目录
目 录 python高级(一)—— python数据模型(特殊方法) python高级(二)—— python内置序列类型 python高级(三)—— 字典和集合(泛映射类型) python高级(四 ...
- python 高级之面向对象初级
python 高级之面向对象初级 本节内容 类的创建 类的构造方法 面向对象之封装 面向对象之继承 面向对象之多态 面向对象之成员 property 1.类的创建 面向对象:对函数进行分类和封装,让开 ...
- python高级之生成器&迭代器
python高级之生成器&迭代器 本机内容 概念梳理 容器 可迭代对象 迭代器 for循环内部实现 生成器 1.概念梳理 容器(container):多个元素组织在一起的数据结构 可迭代对象( ...
- python高级之面向对象高级
python高级之面向对象高级 本节内容 成员修饰符 特殊成员 类与对象 异常处理 反射/自省 单例模式 1.成员修饰符 python的类中只有私有成员和公有成员两种,不像c++中的类有公有成员(pu ...
- python高级之网络编程
python高级之网络编程 本节内容 网络通信概念 socket编程 socket模块一些方法 聊天socket实现 远程执行命令及上传文件 socketserver及其源码分析 1.网络通信概念 说 ...
随机推荐
- servicestack.redis工具类
using System;using System.Collections.Generic;using System.Linq;using ServiceStack.Redis;using Servi ...
- 2PC之JTA原理与实现
转自:https://www.ibm.com/developerworks/cn/java/j-lo-jta/index.html 利用 JTA 处理事务 什么是事务处理 事务是计算机应用中不可或缺的 ...
- linux 下删除乱码文件-乾颐堂
在linux下删除文件,遇到特殊字符是一件非常头疼的事情. 1. 如果文件名带 ‘-’ 或者‘--’这样的字符 删除办法为:rm -- 文件名 如文件名为:-pythontab.tgz 如果用普通方法 ...
- Linux网络配置之虚拟网卡的配置(Red Hat 6.5)
怎么查看当前的网络状态,这里就不着重描述,用ifconfig命令就可以.我们直接进入主题. red hat系统中的网卡配置在这个目录中:/etc/sysconfig/network-scripts 1 ...
- Idea2017常用功能
1,添加java工程 2,导出可执行jar 3,本地代码提交svn新分支 4,乱码问题解决 一次解决所有问题,只需做配置文件的修改即可 解决方案: 在 IntelliJ IDEA 201 ...
- javascript总结41:表格全选反选,经典案例详解
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 编写高质量代码改善C#程序的157个建议——建议67:慎用自定义异常
建议67:慎用自定义异常 除非有充分的理由,否则不要创建自定义异常.如果要对某类程序出错做特殊处理,那就自定义异常.需要自定义异常的理由如下: 1)方便测试.通过抛出一个自定义的异常类型实例,我们可以 ...
- 基于Qt5 跨平台应用开发
1.Qt简介 2.Qt 编程关键技术 2.1 信号与槽 2.2 Qt事件处理 3.Qt开发与实例分析 3.1 开发环境 3.2 系统实现基本框架 3.3 数据库管理 3.5 对Excel进行操作 4. ...
- WinAPI 字符及字符串函数(10): lstrcpy - 复制字符串
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...
- Wait--常见的等待类型
--==================================================================================--SLEEP_BPOOL_FL ...