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中的元类编程入门指引
Apr 15 Python
Python删除windows垃圾文件的方法
Jul 14 Python
python简单实例训练(21~30)
Nov 15 Python
python实现求最长回文子串长度
Jan 22 Python
python实现计数排序与桶排序实例代码
Mar 28 Python
Pandas中Series和DataFrame的索引实现
Jun 27 Python
Python测试模块doctest使用解析
Aug 10 Python
python实现的生成word文档功能示例
Aug 23 Python
win7下 python3.6 安装opencv 和 opencv-contrib-python解决 cv2.xfeatures2d.SIFT_create() 的问题
Oct 24 Python
使用Pytorch来拟合函数方式
Jan 14 Python
Anaconda的安装及其环境变量的配置详解
Apr 22 Python
Django中使用Json返回数据的实现方法
Jun 03 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
phpfans留言版用到的数据操作类和分页类
2007/01/04 PHP
关于初学PHP时的知识积累总结
2013/06/07 PHP
判断php数组是否为索引数组的实现方法
2013/06/13 PHP
php实现微信公众平台账号自定义菜单类
2014/12/02 PHP
PHP之正则表达式捕获组与非捕获组(详解)
2015/07/29 PHP
thinkPHP交易详情查询功能详解
2016/12/02 PHP
Javascript里使用Dom操作Xml
2006/09/20 Javascript
img的onload的另类用法
2008/01/10 Javascript
说说JSON和JSONP 也许你会豁然开朗
2012/09/02 Javascript
子窗体与父窗体传值示例js代码
2013/08/01 Javascript
jquery实现checkbox全选全不选的简单实例
2013/12/31 Javascript
手机端转盘抽奖代码分享
2015/09/10 Javascript
在JavaScript中模拟类(class)及类的继承关系
2016/05/20 Javascript
Javascript闭包与函数柯里化浅析
2016/06/22 Javascript
JS实现的系统调色板完整实例
2016/12/21 Javascript
JavaScript中Require调用js的实例分享
2017/10/27 Javascript
js正则匹配多个全部数据问题
2019/12/20 Javascript
javascript中正则表达式语法详解
2020/08/07 Javascript
vue+elementUI(el-upload)图片压缩,默认同比例压缩操作
2020/08/10 Javascript
python的常见命令注入威胁
2013/02/18 Python
Python实现的井字棋(Tic Tac Toe)游戏示例
2018/01/31 Python
对Python字符串中的换行符和制表符介绍
2018/05/03 Python
浅谈python编译pyc工程--导包问题解决
2019/03/20 Python
python 错误处理 assert详解
2020/04/20 Python
深入解读CSS3中transform变换模型的渲染
2016/05/27 HTML / CSS
关于HTML5的安全问题开发人员需要牢记的
2012/06/21 HTML / CSS
使用HTML5中的contentEditable来将多行文本自动增高
2016/03/01 HTML / CSS
德国最大的网上鞋店之一:Schuhe24.de
2017/06/10 全球购物
青年创业培训欢迎词
2014/01/10 职场文书
大学生社会实践活动总结
2014/07/03 职场文书
家长学校培训材料
2014/08/20 职场文书
奥巴马经典演讲稿
2014/09/13 职场文书
普通党员个人整改措施
2014/10/27 职场文书
python process模块的使用简介
2021/05/14 Python
Java基础——Map集合
2022/04/01 Java/Android
nginx lua 操作 mysql
2022/05/15 Servers