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 相关文章推荐
Python3 循环语句(for、while、break、range等)
Nov 20 Python
PyQt5实现无边框窗口的标题拖动和窗口缩放
Apr 19 Python
Python使用sklearn库实现的各种分类算法简单应用小结
Jul 04 Python
基于Pycharm加载多个项目过程图解
Jan 19 Python
浅谈Pytorch中的自动求导函数backward()所需参数的含义
Feb 29 Python
python3注册全局热键的实现
Mar 22 Python
python pandas.DataFrame.loc函数使用详解
Mar 26 Python
keras 如何保存最佳的训练模型
May 25 Python
Python使用for生成列表实现过程解析
Sep 22 Python
python 常见的反爬虫策略
Sep 27 Python
python Polars库的使用简介
Apr 21 Python
Python实现简单的猜单词
Jun 15 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 在文件指定行插入数据的代码
2010/05/08 PHP
PHP学习笔记之数组篇
2011/06/28 PHP
php jquery 多文件上传简单实例
2013/12/23 PHP
PHP7匿名类用法分析
2016/09/26 PHP
Laravel如何自定义command命令浅析
2019/03/23 PHP
js如何获取object类型里的键值
2014/02/18 Javascript
多个checkbox被选中时如何判断是否有自己想要的
2014/09/22 Javascript
JavaScript设计模式之单例模式实例
2014/09/24 Javascript
jQuery实现友好的轮播图片特效
2015/01/12 Javascript
JQuery radio(单选按钮)操作方法汇总
2015/04/15 Javascript
jQuery实现有动画淡出效果的二级折叠菜单代码
2015/10/17 Javascript
微信小程序 封装http请求实例详解
2017/01/16 Javascript
从零学习node.js之利用express搭建简易论坛(七)
2017/02/25 Javascript
JavaScript与JQUERY获取元素的宽、高和位置
2017/02/26 Javascript
详解创建自定义的Angular Schematics
2018/06/06 Javascript
vue删除html内容的标签样式实例
2018/09/13 Javascript
Node.js+ELK日志规范的实现
2019/05/23 Javascript
vue 框架下自定义滚动条(easyscroll)实现方法
2019/08/29 Javascript
详解小程序云开发攻略(解决最棘手的问题)
2019/09/30 Javascript
Python实现爬虫从网络上下载文档的实例代码
2018/06/13 Python
使用django-guardian实现django-admin的行级权限控制的方法
2018/10/30 Python
使用50行Python代码从零开始实现一个AI平衡小游戏
2018/11/21 Python
python3使用flask编写注册post接口的方法
2018/12/28 Python
深入了解Python 方法之类方法 &amp; 静态方法
2020/08/17 Python
python中strip(),lstrip(),rstrip()函数的使用讲解
2020/11/17 Python
详解如何解决H5开发使用wx.hideMenuItems无效果不生效
2021/01/20 HTML / CSS
Holland & Barrett爱尔兰:英国领先的健康零售商
2019/03/31 全球购物
大一学生假期实习的自我评价
2013/10/12 职场文书
大学生自我鉴定
2013/12/16 职场文书
应届毕业生求职信范文分享
2013/12/26 职场文书
《长城和运河》教学反思
2014/04/14 职场文书
校园绿化美化方案
2014/06/08 职场文书
2014年学生会干事工作总结
2014/11/07 职场文书
投资入股协议书
2016/03/22 职场文书
Python matplotlib 利用随机函数生成变化图形
2022/04/26 Python
一文搞懂PHP中的抽象类和接口
2022/05/25 PHP