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 相关文章推荐
python基础教程之数字处理(math)模块详解
Mar 25 Python
python数据结构之二叉树的统计与转换实例
Apr 29 Python
Python Socket传输文件示例
Jan 16 Python
python基础教程之Filter使用方法
Jan 17 Python
Python结巴中文分词工具使用过程中遇到的问题及解决方法
Apr 15 Python
influx+grafana自定义python采集数据和一些坑的总结
Sep 17 Python
Python利用递归实现文件的复制方法
Oct 27 Python
在python中按照特定顺序访问字典的方法详解
Dec 14 Python
python设定并获取socket超时时间的方法
Jan 12 Python
对python函数签名的方法详解
Jan 22 Python
简单了解python gevent 协程使用及作用
Jul 22 Python
pycharm 对代码做静态检查操作
Jun 09 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实现ping
2006/10/09 PHP
提升PHP执行速度全攻略(下)
2006/10/09 PHP
使用数据库保存session的方法
2006/10/09 PHP
PHP Session变量不能传送到下一页的解决方法
2009/11/27 PHP
php microtime获取浮点的时间戳
2010/02/21 PHP
php 7新特性之类型申明详解
2017/06/06 PHP
PHP长连接实现与使用方法详解
2018/02/11 PHP
让JavaScript拥有类似Lambda表达式编程能力的方法
2010/09/12 Javascript
不用构造函数(Constructor)new关键字也能实现JavaScript的面向对象
2013/01/11 Javascript
浅析JQuery获取和设置Select选项的常用方法总结
2013/07/04 Javascript
javascript实现复制与粘贴操作实例
2014/10/16 Javascript
js判断当前页面在移动设备还是在PC端中打开
2016/01/06 Javascript
JS实现六位字符密码输入器功能
2016/08/19 Javascript
jquery将标签元素的高设为屏幕的百分比
2017/04/19 jQuery
解决webpack打包速度慢的解决办法汇总
2017/07/06 Javascript
AngularJS中ng-options实现下拉列表的数据绑定方法
2018/08/13 Javascript
Vue组件模板及组件互相引用代码实例
2020/03/11 Javascript
JS原型prototype和__proto__用法实例分析
2020/03/14 Javascript
[03:59]第二届DOTA2亚洲邀请赛选手传记-VGJ.rOtk
2017/04/03 DOTA
Python实现的爬取百度文库功能示例
2019/02/16 Python
python实现弹窗祝福效果
2019/04/07 Python
python仿evething的文件搜索器实例代码
2019/05/13 Python
浅谈python 中类属性共享的问题
2019/07/02 Python
大家都说好用的Python命令行库click的使用
2019/11/07 Python
使用 Python 在京东上抢口罩的思路详解
2020/02/27 Python
L’urv官网:精品女性运动服品牌
2019/07/07 全球购物
小组名称和口号
2014/06/09 职场文书
绿色环保口号
2014/06/12 职场文书
森林防火宣传标语
2014/06/27 职场文书
社团活动总结模板
2014/06/30 职场文书
学校教师读书活动总结
2014/07/08 职场文书
教师考核表个人总结
2015/02/12 职场文书
节水宣传标语口号
2015/12/26 职场文书
实习员工转正的评语汇总,以备不时之需
2019/12/17 职场文书
Vue3.0中Ref与Reactive的区别示例详析
2021/07/07 Vue.js
WebWorker 封装 JavaScript 沙箱详情
2021/11/02 Javascript