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 27 Python
详解Python中的__new__、__init__、__call__三个特殊方法
Jun 02 Python
Python中文分词实现方法(安装pymmseg)
Jun 14 Python
详解Python进程间通信之命名管道
Aug 28 Python
解决python3中自定义wsgi函数,make_server函数报错的问题
Nov 21 Python
python文件操作之批量修改文件后缀名的方法
Aug 10 Python
python解析含有重复key的json方法
Jan 22 Python
pandas对dataFrame中某一个列的数据进行处理的方法
Jul 08 Python
Python3enumrate和range对比及示例详解
Jul 13 Python
彻底搞懂 python 中文乱码问题(深入分析)
Feb 28 Python
Python Flask上下文管理机制实例解析
Mar 16 Python
python wsgiref源码解析
Feb 06 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
德生S2000收音机更换“钕铁硼”全频扬声器
2021/03/02 无线电
巧用php中的array_filter()函数去掉多维空值的代码分享
2012/09/07 PHP
php存储过程调用实例代码
2013/02/03 PHP
PHP 解决session死锁的方法
2013/06/20 PHP
php记录代码执行时间(实现代码)
2013/07/05 PHP
CI映射(加载)数据到view层的方法
2016/03/28 PHP
php封装实现钉钉机器人报警接口的示例代码
2020/08/08 PHP
Yii中特殊行为ActionFilter的使用方法示例
2020/10/18 PHP
用js实现的检测浏览器和系统的函数
2009/04/09 Javascript
基于jquery的button默认enter事件(回车事件)。
2011/05/18 Javascript
jquery js 重置表单 reset()具体实现代码
2013/08/05 Javascript
web前端设计师们常用的jQuery特效插件汇总
2014/12/07 Javascript
javascript的tab切换原理与效果实现方法
2015/01/10 Javascript
javascript 实现 原路返回
2015/01/21 Javascript
AngularJS基础学习笔记之控制器
2015/05/10 Javascript
jQuery获取checkbox选中的值
2016/01/28 Javascript
Angular.js回顾ng-app和ng-model使用技巧
2016/04/26 Javascript
js带闹铃功能的倒计时代码
2016/09/29 Javascript
浅谈MVC+EF easyui dataGrid 动态加载分页表格
2016/11/10 Javascript
Vue之Vue.set动态新增对象属性方法
2018/02/23 Javascript
vue中的router-view组件的使用教程
2018/10/23 Javascript
jQuery实现可编辑的表格
2019/12/11 jQuery
详解node.js创建一个web服务器(Server)的详细步骤
2021/01/15 Javascript
浅谈python中的实例方法、类方法和静态方法
2017/02/17 Python
Python简单生成随机姓名的方法示例
2017/12/27 Python
python之django母板页面的使用
2018/07/03 Python
EMPHASIS艾斐诗官网:周生生旗下原创精品珠宝品牌
2020/12/17 全球购物
linux比较文件内容的命令是什么
2013/03/04 面试题
JS原生实现轮播图的几种方法
2021/03/23 Javascript
八一建军节感言
2014/02/28 职场文书
2014年酒店服务员工作总结
2014/12/08 职场文书
应届生求职自荐信范文
2015/03/04 职场文书
污染环境建议书
2015/09/14 职场文书
pytorch中的model=model.to(device)使用说明
2021/05/24 Python
《LOL》“克隆大作战”久违归来 幻灵战队皮肤上线
2022/04/03 其他游戏
Android在Sqlite3中的应用及多线程使用数据库的建议
2022/04/24 Java/Android