前言

前面已经总结了关键字、运算符与魔法方法的对应关系,下面总结python内置函数对应的魔法方法。

魔法方法

数学计算

  1. abs(args):返回绝对值,调用__abs__;
  2. round(args):返回四舍五入的值,调用__round__;
  3. math.floor():向下取整,调用__floor__;
  4. math.ceil():向上取整,调用__ceil__;
  5. math.trunc():求一个值距离0最近的整数,调用__trunc__;
  6. divmod(a,b):返回商和余,调用__divmod__;
  7. pow(a,b):返回幂,调用__pow__;
  8. sum():返回和,调用__sum__;
  9. float():转换小数,调用__float__;
  10. int():转换整数,调用__int__;
  11. str():转换字符串,调用__str__;
  12. sys.getsizeof():对象占内存的大小,调用__sizeof__;
  13. bin(*args, **kwargs):调用参数的__bin__方法,返回整数的二进制表示形式,只支持一个参数,只支持int类型
  14. hash():调用__hash__方法,获取一个对象的散列值,相等的两个数哈希值相等,反过来不一定成立
  15. hex(*args, **kwargs):调用__hex__方法,求整数的十六进制表示形式,只支持Int类型
  16. oct(*args, **kwargs):调用__oct__方法,求整数的八进制表示形式,只支持Int类型

访问控制

  1. __getattr__(self, name):getattr方法触发,仅对对象未定义的属性有效,即如果视图获取一个没有的属性时会调用该方法,前提是该对象未定义__getattribute__(self, name)方法;
  2. __getattribute__(self, name):getattr方法触发,如果对象定义了该方法,一定触发,__getattr__方法将不会被调用;它也可以被self.name语法糖触发;
  3. __setattr__(self, name, value):setattr方法触发,设置一个对象的属性;也可以被self.name = ''语法糖触发。
  4. __delattr__(self, name):delattr方法触发,删除一个对象的属性,或由del self.name 形式触发;

容器类型

在Python中实现自定义容器类型需要用到一些协议。不可变容器类型有如下协议:

  1. 不可变容器,需要定义 _len_ 和 _getitem_ ;
  2. 可变容器,需要定义 _len_ 、_getitem_、_setitem_、_delitem_ ;
  3. 容器可迭代,需要定义 _iter_
  4. 迭代器,必须遵守迭代器协议,需要定义 _iter_ 和 _next_ 方法。
  • 索引语法糖与魔法方法
  1. __len__(self):返回容器的长度;
  2. __getitem__(self, key):使用self[key]形式语法糖获取元素会触发;
  3. __setitem__(self, key):使用self[key] = 'xxx'形式复制会触发;
  4. __delitem__(self, key):使用del self[key]语法糖触发
  5. __reversed__(self):reversed(self)触发,反转容器;
  6. __missing__(self, key):字典结构使用self[key]形式获取元素,如果元素不存在触发;
  • 分片语法糖与魔法方法

切片在底层的原理,py2和py3有很大的不同,py2中使用_getslice_、_setslice_、__delslice__三个魔法方法控制,py3中将索引和切片统一由_getitem_、_setitem_、__delitem__控制。

  1. # py2中
  2. ls = [1,2,3,4]
  3. print(ls[1:3]) # py2中该语法糖调用__getslice__方法,py3中废弃
  4. del ls[1:3] # py2中该语法糖调用__delslice__方法,py3中废弃
  5. ls[1:3] = [1,2,2] # py2中该语法糖调用__setslice__方法,py3中废弃
  1. # py3中
  2. class Person(object):
  3. def __getitem__(self, item):
  4. print(item)
  5. return 'getitem'
  6. def __setitem__(self, key, value):
  7. print(key, value)
  8. return 'setitem'
  9. def __delitem__(self, key):
  10. print(key)
  11. return 'delitem'
  12. if __name__ == "__main__":
  13. person = Person()
  14. print(person[0]) # person[0] ==> person.__getitem__(0)
  15. print(person[0:2]) # person[0:2] ==> person.__getitem__(slice(0,2,None))
  16. person[0:2] = 'test' # ==> person.__setitem__(slice(0,2,None), 'test')
  17. del person[0:2] # ==> person.__delitem__(slice(0,2,None))
  18. # 结果
  19. 0
  20. getitem
  21. slice(0, 2, None)
  22. getitem
  23. slice(0, 2, None) test
  24. slice(0, 2, None)

python在处理索引语法糖的时候,将索引当做参数传入相关getitem、setitem、delitem的魔法方法;在处理切片语法糖的时候先调用slice方法得到slice实例对象,将其作为参数调用相关的魔法方法。

拷贝

  1. __copy__(self):如果对象定义了该方法,copy.copy()就会调用该方法返回拷贝对象;
  2. __deepcopy__(self, x):如果对象定义了该方法,copy.deepcopy()就会调用该方法返回拷贝对象;

序列化

序列化我们可以简单理解成对任何数据的一种描述方法,如果多种平台遵循了相同的序列化协议,数据之间的传递就会变得方便。python默认的序列化模块为pickle。

  • 序列化的简单例子
  1. class Person(object):
  2. def __init__(self):
  3. self.name = 'cai'
  4. if __name__ == "__main__":
  5. import pickle
  6. person = Person()
  7. with open('./person.txt', 'wb') as f:
  8. # 序列化后存储
  9. pickle.dump(person,f)
  10. with open('./person.txt', 'rb') as f:
  11. # 反序列化
  12. per = pickle.load(f)
  13. print(per.name)
  14. # 我们可以把一个类保存起来,后续读取它直接使用。
  • 相关的魔法方法
  1. __getinitargs__(self):该魔法方法在py3中似乎被废弃,原本的功能是在序列化时获取实例化参数,应该返回一个元组;
  2. __getnewargs__(self):对新式类,通过这个方法改变类在反pickle时传递给__new__ 的参数;应该返回一个参数元组。
  3. __getstate__(self):定义对象被序列化时的状态,而不使用对象的 __dict__ 属性,必须返回一个字典,他会去替代 __dict__ 属性,在序列化时被调用;
  4. __setstate__(self,state):当一个对象被反pickle时,如果定义了 __setstate__ ,对象的状态会传递给这个魔法方法,而不是直接应用到对象的 __dict__ 属性, state参数是序列化前的__dict__属性。
  1. class Person(object):
  2. def __init__(self,name):
  3. print('init')
  4. self.name = name
  5. def __getinitargs__(self):
  6. print('initargs')
  7. return 'zhao',
  8. def __getnewargs__(self):
  9. print('newargs')
  10. return 'wang',
  11. def __getstate__(self):
  12. print('getstate')
  13. return {'name':'xiao'}
  14. def __setstate__(self, state):
  15. print('setstate')
  16. print(state)
  17. self.__dict__ = state
  18. if __name__ == "__main__":
  19. import pickle
  20. person = Person('cai')
  21. with open('./person.txt', 'wb') as f:
  22. # 序列化后存储
  23. pickle.dump(person,f)
  24. with open('./person.txt', 'rb') as f:
  25. # 反序列化
  26. per = pickle.load(f)
  27. print(per.name)
  28. # 结果
  29. __new__
  30. init
  31. newargs
  32. getstate
  33. __new__
  34. setstate
  35. {'name': 'xiao'}
  36. xiao

说明:

  1. pickle序列化对象之前,先执行__getnewargs__或__new__方法的参数;

  2. 然后执行__getstate__方法,返回的值替代对象的__dict__属性值;

  3. 反序列化时调用new方法,以getnewargs返回的值作为参数创建实例;

  4. 最后调用__setstate__方法,将getstate方法的返回值作为state参数;

  5. 所以由于反序列化时不会调用init方法初始化,getinitargs和getnewargs方法的作用都变得不大;

其他

  1. __instancecheck__(self, instance):instance触发,判断对象的类型
  2. __subclasscheck__(self, subclass):issubclass触发,判断一个对象是另一个对象的子类;
  3. __call__:callable触发,判断一个对象是否可调用;
  4. __dir__(self):dir()触发,获取对象的所有属性、方法的名字组成的列表;
  • __str_和_repr

调用str触发_str_,调用repr()触发_repr_,但是print()也可以触发__str_和_repr,如果对象定义了_str_,则print()一般触发_str_,否则触发_repr_;但列表以及字典等容器总是会使用_repr_ 方法.

__str__和__repr__的区别

  1. 一般来说,_str_ 的返回结果在于强可读性,而 _repr_ 的返回结果在于准确性;

  2. 默认情况下,在需要却找不到 __str__方法的时候,会自动调用 _repr_ 方法。

总结

熟悉了python语法糖、内置函数与魔法方法之间的关系后,显然对于如何写好一个优雅易用的类有很大的帮助。

参考

python进阶之内置函数和语法糖触发魔法方法的更多相关文章

  1. python进阶之内置方法

    python进阶之内置方法 字符串类型的内置方法 常用操作与方法: 按索引取值 str[index] 切片 ste[start:stop:step] 长度 len(str) 成员运算in和not in ...

  2. Python基础之内置函数(二)

    先上一张图,python中内置函数: python官方解释在这:点我点我 继续聊内置函数: callable(object):检查对象是否可被调用,或是否可执行,结果为bool值 def f1(): ...

  3. Python基础之内置函数和递归

    一.内置函数 下面简单介绍几个: 1.abs() 求绝对值 2.all() 如果 iterable 的所有元素都为真(或者如果可迭代为空),则返回 True 3.any() 如果 iterable 的 ...

  4. python基础之内置函数补充、匿名函数、递归函数

    内置函数补充 python divmod()函数:把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b) 语法: 1 divmod(a, b) #a.b为数字,a为除数 ...

  5. python基础之内置函数

    该博客内容参考http://www.cnblogs.com/wupeiqi/articles/4943406.html 内置函数 一 详细见python文档,猛击这里 文件操作 操作文件时,一般需要经 ...

  6. python基础之内置函数和匿名函数

      内置函数 学习函数以后多了很多概念,例如函数的命名空间,函数的作用域,函数的调用等等,函数的作用就是为了实现某些功能而方便以后可以调用,内置函数就是这样的一些公共的函数,被称为内置函数. 我们就一 ...

  7. python学习之内置函数(二)

    4.7.3 内置函数(2) int() str() bool() set() list():将一个可迭代对象转化为列表 tuple():将一个可迭代对象转换成元组 dic(): 通过相应的方式创建字典 ...

  8. Python系列之内置函数

    内置函数 一.数学运算类: abs(a):求绝对值如果参数是个复数则返回复数的模. a = abs(-1) print(a) >>>1 compilex([real[, imag]] ...

  9. python学习之内置函数(一)

    4.7 内置函数 4.7.1 内置函数(1) eval 执行字符串类型的代码,并返回最终结果. eval('2 + 2') # 4 n=81 eval("n + 4") # 85 ...

随机推荐

  1. 第103天:CSS3中Flex布局(伸缩布局)详解

    一.Flex布局 Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性. 任何一个容器都可以指定为Flex布局. .box{ display: flex; } 行 ...

  2. HDU4747——2013 ACM/ICPC Asia Regional Hangzhou Online

    啦啦啦. 这是杭州网赛的一个题目,当时没做出来,当然这个想法确实比较难想到. 题目质量很高,这个题目也很特别,以前都没做过类似的题目.让我又一次体验了线段树的强大力量. 题目的意思是给你n个数a1-a ...

  3. java finally 与return

    finally之外的语句块有return,finally语句块没有return:该语句块的返回值被固定下来,等fianlly执行完后返回给调用者 finally语句块与其他语句块同时有return:返 ...

  4. 【刷题】LOJ 6038 「雅礼集训 2017 Day5」远行

    题目描述 Miranda 生活的城市有 \(N\) 个小镇,一开始小镇间没有任何道路连接.随着经济发现,小镇之间陆续建起了一些双向的道路但是由于经济不太发达,在建设过程中,会保证对于任意两个小镇,最多 ...

  5. 被动式pocscan扫描神器搭建

    1.搭建环境: 操作系统为:ubuntu16.04 x64位系统,内核版本3.0.10以上 2.安装docker镜像 root@backlion-virtual-machine:/# apt-get ...

  6. Linux内核分析2

    周子轩原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 本次实验是通过分析一个简单 ...

  7. [HNOI2006]最短母串问题——AC自动机+状压+bfs环形处理

    Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 32MB Input 第一行是一个正整数n(n< ...

  8. 【loj2133】【NOI2015】品酒大会

    Portal --> loj2133 Solution 虽然说这题貌似用后缀树之类的好像会更加简短一点..但是还是因为在智力康复所以就还是用后缀数组好了嗯(哇好感动啊难得那么顺畅写了一道noi的 ...

  9. git使用经验(一)

    在使用Git Push代码到数据仓库时,提示如下错误: [remote rejected] master -> master (branch is currently checked out) ...

  10. Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1)A B C 水 并查集 思路

    A. Bear and Big Brother time limit per test 1 second memory limit per test 256 megabytes input stand ...