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下安装python2.7及科学计算套装
Mar 05 Python
PyQt5实现无边框窗口的标题拖动和窗口缩放
Apr 19 Python
python启动应用程序和终止应用程序的方法
Jun 28 Python
python数据归一化及三种方法详解
Aug 06 Python
Python中的引用和拷贝实例解析
Nov 14 Python
tensorflow自定义激活函数实例
Feb 04 Python
基于python检查SSL证书到期情况代码实例
Apr 04 Python
Python如何安装第三方模块
May 28 Python
python中执行smtplib失败的处理方法
Jul 01 Python
详解Python3 定义一个跨越多行的字符串的多种方法
Sep 06 Python
python统计mysql数据量变化并调用接口告警的示例代码
Sep 21 Python
python 实现图片修复(可用于去水印)
Nov 19 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令牌 Token改进版
2008/07/18 PHP
PHP动态分页函数,PHP开发分页必备啦
2011/11/07 PHP
浅析ThinkPHP中execute和query方法的区别
2014/06/13 PHP
destoon安装出现Internal Server Error的解决方法
2014/06/21 PHP
js基于qrcode.js生成二维码的方法【附demo插件源码下载】
2016/12/28 PHP
PHP多线程模拟实现秒杀抢单
2018/02/07 PHP
YII框架模块化处理操作示例
2019/04/26 PHP
初识javascript 文档碎片
2010/07/13 Javascript
鼠标滑上去后图片放大浮出效果的js代码
2011/05/28 Javascript
5个最佳的Javascript日期处理类库分享
2012/04/15 Javascript
JS 控件事件小结
2012/10/31 Javascript
jquery二级导航内容均分的原理及实现
2013/08/13 Javascript
jQuery使用ajax跨域获取数据的简单实例
2016/05/18 Javascript
基于JavaScript实现添加到购物车效果附源码下载
2016/08/22 Javascript
Angular组件化管理实现方法分析
2017/03/17 Javascript
Vue2.0学习之详解Vue 组件及父子组件通信
2017/12/12 Javascript
Sublime Text3 配置 NodeJs 环境的方法
2020/05/20 NodeJs
[47:10]完美世界DOTA2联赛PWL S3 LBZS vs Rebirth 第二场 12.16
2020/12/18 DOTA
[52:07]完美世界DOTA2联赛PWL S3 LBZS vs access 第二场 12.10
2020/12/13 DOTA
python检查字符串是否是正确ISBN的方法
2015/07/11 Python
Python2 与Python3的版本区别实例分析
2020/03/30 Python
python 最简单的实现适配器设计模式的示例
2020/06/30 Python
Python容器类型公共方法总结
2020/08/19 Python
Python用Jira库来操作Jira
2020/12/28 Python
html5使用canvas绘制文字特效
2014/12/15 HTML / CSS
美国著名的婴儿学步鞋老品牌:Robeez
2016/08/20 全球购物
阿联酋手表和配饰购物网站:Rivolishop
2019/11/25 全球购物
C/C++ 笔试、面试题目大汇总
2015/11/21 面试题
就业自荐书
2013/12/05 职场文书
导购员的岗位职责
2014/02/08 职场文书
小学学习雷锋活动总结
2014/07/03 职场文书
公司授权委托书
2014/10/17 职场文书
小兵张嘎观后感
2015/06/03 职场文书
如何利用JavaScript实现二叉搜索树
2021/04/02 Javascript
大型强子对撞机再次重启探索“第五种自然力”
2022/04/29 数码科技
NoSQL优缺点与MongoDB数据库简介
2022/06/05 MongoDB