Python中的特殊方法以及应用详解


Posted in Python onSeptember 20, 2020

前言

Python 中的特殊方法主要是为了被解释器调用的,因此应该尽量使用 len(my_object) 而不是 my_object.__len__() 这种写法。在执行 len(my_object) 时,Python 解释器会自行调用 my_object 中实现的 __len__ 方法。

除非有大量的元编程存在,直接调用特殊方法的频率应远小于实现它们的次数。

模拟数值类型

可以通过在自定义对象中实现 __add__ 和 __mul__ 等特殊方法 ,令其支持 +、* 等运算符。

如下面的模拟向量的 Vector 类:

# vector.py
from math import hypot

class Vector:
  def __init__(self, x=0, y=0):
    self.x = x
    self.y = y

  def __repr__(self):
    return f'Vector({self.x}, {self.y})'

  def __abs__(self):
    return hypot(self.x, self.y)

  def __bool__(self):
    return bool(self.x or self.y)

  def __add__(self, other):
    return Vector(self.x + other.x, self.y + other.y)

  def __mul__(self, scalar):
    return Vector(self.x * scalar, self.y * scalar)

运行效果如下:

>>> from vector import Vector
>>> v1 = Vector(2, 4)
>>> v2 = Vector(2, 1)
>>> v1 + v2
Vector(4, 5)
>>> v = Vector(3, 4)
>>> abs(v)
5.0
>>> v * 3
Vector(9, 12)

对象的字符串表示

Python 有一个 repr 内置函数,能把一个对象用字符串的形式表示出来。实际上这种字符串表达是通过对象内部的 __repr__ 特殊方法定义的。默认情况下,在控制台里查看某个对象时,输出的字符串一般是 <xxx object at 0x7fc99d6ab2e0> 这种形式。

__repr__ 返回的字符串应该准确、无歧义,并尽可能表示出该对象是如何创建的。比如前面的 Vector 对象,其 __repr__ 中定义的字符串形式类似于 Vector(3, 4),和对象初始化的语法非常近似。

__repr__ 和 __str__ 的区别在于,__str__ 是在向对象应用 str() 函数(或者用 print 函数打印某个对象)时被调用。其返回的字符串对终端用户更友好。

如果只想实现其中一个特殊方法,__repr__ 应该是更优的选择。在对象没有实现 __str__ 方法的情况下,Python 解释器会用 __repr__ 代替。

# myclass.py
class MyClass:
  def __repr__(self):
    return 'MyClass'

  def __str__(self):
    return 'This is an instance of MyClass'
>>> from myclass import MyClass
>>> my = MyClass()
>>> my
MyClass
>>> print(my)
This is an instance of MyClass

自定义布尔值

Python 里有 bool 类型,但实际上任何对象都可以用在需要 bool 类型的上下文(比如 if 或 while 语句)中。为了判断某个值 x 的真假,Python 会调用 bool(x) 返回 True 或 False。

默认情况下,自定义类的实例总是为真。除非这个类对于 __bool__ 或 __len__ 方法有自己的实现。
bool(x) 实际上调用了对象 x 中的 __bool__ 方法。如不存在 __bool__ 方法,则 bool(x) 会尝试调用 x.__len__(),返回 0 则为 False,否则为 True。

# boolclass.py
class BoolClass:
  def __init__(self):
    self.list = []

  def add(self, item):
    self.list.append(item)

  def __len__(self):
    return len(self.list)
>>> from boolclass import BoolClass
>>> b = BoolClass()
>>> len(b)
0
>>> bool(b)
False
>>> b.add(1)
>>> len(b)
1
>>> bool(b)
True
# boolclass.py
class BoolClass:
  def __init__(self):
    self.list = []

  def add(self, item):
    self.list.append(item)

  def __len__(self):
    return len(self.list)

  def __bool__(self):
    return bool(sum(self.list))
>>> from boolclass import BoolClass
>>> b = BoolClass()
>>> b.add(1)
>>> len(b)
1
>>> bool(b)
True
>>> b.add(-1)
>>> len(b)
2
>>> bool(b)
False

参考资料

Fluent Python

总结

到此这篇关于Python中特殊方法以及应用详解的文章就介绍到这了,更多相关Python特殊方法及应用内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Windows下搭建python开发环境详细步骤
Jul 20 Python
python使用opencv进行人脸识别
Apr 07 Python
使用python生成杨辉三角形的示例代码
Aug 29 Python
python 同时运行多个程序的实例
Jan 07 Python
python用requests实现http请求代码实例
Oct 31 Python
Python 静态方法和类方法实例分析
Nov 21 Python
python实现多进程按序号批量修改文件名的方法示例
Dec 30 Python
使用Matplotlib绘制不同颜色的带箭头的线实例
Apr 17 Python
python利用线程实现多任务
Sep 18 Python
Django 用户认证Auth组件的使用
Nov 30 Python
利用python查看数组中的所有元素是否相同
Jan 08 Python
Django中的JWT身份验证的实现
May 07 Python
matplotlib 三维图表绘制方法简介
Sep 20 #Python
Python三维绘图之Matplotlib库的使用方法
Sep 20 #Python
scrapy利用selenium爬取豆瓣阅读的全步骤
Sep 20 #Python
Python操作dict时避免出现KeyError的几种解决方法
Sep 20 #Python
python中random.randint和random.randrange的区别详解
Sep 20 #Python
详解如何在pyqt中通过OpenCV实现对窗口的透视变换
Sep 20 #Python
Python Pillow(PIL)库的用法详解
Sep 19 #Python
You might like
php桌面中心(二) 数据库写入
2007/03/11 PHP
php自动获取字符串编码函数mb_detect_encoding
2011/05/31 PHP
PHP生成压缩文件实例
2015/02/07 PHP
PHP日志LOG类定义与用法示例
2018/09/06 PHP
php post换行的方法
2020/02/03 PHP
Gambit vs CL BO3 第三场 2.13
2021/03/10 DOTA
项目实践之javascript技巧
2007/12/06 Javascript
JS中setTimeout()的用法详解
2013/04/14 Javascript
Three.js学习之网格
2016/08/10 Javascript
js实现String.Fomat的实例代码
2016/09/02 Javascript
Centos7 中安装 Node.js v4.4.4
2016/11/03 Javascript
在js里怎么实现Xcode里的callFuncN方法(详解)
2016/11/05 Javascript
JavaScript实现图片懒加载(Lazyload)
2016/11/28 Javascript
jQuery实现花式轮播之圣诞节礼物传送效果
2016/12/25 Javascript
jqgrid实现简单的单行编辑功能
2017/09/30 Javascript
什么时候不能在 Node.js 中使用 Lock Files
2019/06/24 Javascript
使用flow来规范javascript的变量类型
2019/09/12 Javascript
压缩Vue.js打包后的体积方法总结(Vue.js打包后体积过大问题)
2020/02/03 Javascript
基于脚手架创建Vue项目实现步骤详解
2020/08/03 Javascript
python实现批量改文件名称的方法
2015/05/25 Python
Python面向对象class类属性及子类用法分析
2018/02/02 Python
Python将图片转换为字符画的方法
2020/06/16 Python
python 2.7.13 安装配置方法图文教程
2018/09/18 Python
python3 自动识别usb连接状态,即对usb重连的判断方法
2019/07/03 Python
Python常用编译器原理及特点解析
2020/03/23 Python
Python基于requests实现模拟上传文件
2020/04/21 Python
Python实现http接口自动化测试的示例代码
2020/10/09 Python
python Gabor滤波器讲解
2020/10/26 Python
matplotlib绘制多子图共享鼠标光标的方法示例
2021/01/08 Python
python 爬取腾讯视频评论的实现步骤
2021/02/18 Python
html5如何及时更新缓存文件(js、css或图片)
2013/06/24 HTML / CSS
Origins悦木之源香港官网:雅诗兰黛集团高端植物护肤品牌
2018/03/21 全球购物
Linux不知道文件后缀名怎么判断文件类型
2012/04/26 面试题
退休教师欢送会主持词
2014/03/31 职场文书
2015年保洁员工作总结
2015/05/04 职场文书
Win11更新失败并提示0xc1900101
2022/04/19 数码科技