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.网络通信概念 说 ...
随机推荐
- .net 多线程同步的相关知识点
在多线程开发中,共享对象的同步是经常遇到的问题,以下总结了C#中线程同步的几种技术: 1,InterLocked原子操作 Decrement(ref int location);递减1 Add(ref ...
- mongodb修改用户名密码
首先先将启动mongo的配置文件里面的 auth:用户认证,改为false. 正确做法,利用db.changeUserPassword db.changeUserPassword('tank2','t ...
- java中List的用法和实例详解
java中List的用法和实例详解 List的用法List包括List接口以及List接口的所有实现类.因为List接口实现了Collection接口,所以List接口拥有Collection接口提供 ...
- aspnetcore的那些actionresult们
比MVC5多了n个actionresult,傻傻分不清,整理了下,妈妈再也不用担心了 https://docs.asp.net/projects/api/en/latest/autoapi/Micro ...
- HDU 3361 ASCII (水题)
题意: 析:不说话. #include <cstdio> #include <string> #include <cstdlib> #include <cma ...
- Linux内核版本
在Linux中找到/usr/src/kernels/目录,该目录下面有一个系统内核文件 例如:2.6.32-431.11.2.el6.x86_64 Linux内核版本规则 Linux内核版本有三组数字 ...
- Web大文件(夹)上传(断点续传)控件发布-Xproer.HttpUploader6
版权所有 2009-2017荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...
- mybatis 配置延迟加载 和 缓存
<!-- MyBatis延迟加载时,创建代理类 --> <dependency> <groupId>cglib</groupId> <artifa ...
- mybatis 存储过程调用
接口 UserInfoMapper.java xml UserInfoMapper.xml 如何关联 <?xml version="1.0" encoding=" ...
- 编写高质量代码改善C#程序的157个建议——建议71:区分异步和多线程应用场景
建议71:区分异步和多线程应用场景 初学者有时候会将异步和多线程混为一谈.如果对它们之间的区别不是很清楚,很容易写出下面这样的代码: private void buttonGetPage_Click( ...