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类的基础入门知识
Nov 24 Python
python list转dict示例分享
Jan 28 Python
Python使用稀疏矩阵节省内存实例
Jun 27 Python
python中类的一些方法分析
Sep 25 Python
举例详解Python中yield生成器的用法
Aug 05 Python
Python自定义函数计算给定日期是该年第几天的方法示例
May 30 Python
Django实现文件上传下载功能
Oct 06 Python
在Tensorflow中查看权重的实现
Jan 24 Python
python多项式拟合之np.polyfit 和 np.polyld详解
Feb 18 Python
自学python用什么系统好
Jun 23 Python
Python高阶函数与装饰器函数的深入讲解
Nov 10 Python
selenium判断元素是否存在的两种方法小结
Dec 07 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的可变变量名需要的注意的问题
2013/06/20 PHP
php以post形式发送xml的方法
2014/11/04 PHP
迁移PHP版本到PHP7
2015/02/06 PHP
php校验表单检测字段是否为空的方法
2015/03/20 PHP
php解析url并得到url中的参数及获取url参数的四种方式
2015/10/26 PHP
Zend Framework创建自己的动作助手详解
2016/03/05 PHP
YII动态模型(动态表名)支持分析
2016/03/29 PHP
laravel 根据不同组织加载不同视图的实现
2019/10/14 PHP
浅析LigerUi开发中谨慎载入common.css文件
2013/07/09 Javascript
javascript实现yield的方法
2013/11/06 Javascript
JS中数组Array的用法示例介绍
2014/02/20 Javascript
JavaScript中的方法调用详细介绍
2014/12/30 Javascript
jQuery实现感应鼠标动画效果自动伸长的输入框实例
2015/02/24 Javascript
JS产生随机数的几个用法详解
2016/06/22 Javascript
js实现下拉菜单效果
2017/03/01 Javascript
JavaScript中document.referrer的用法详解
2017/07/04 Javascript
对于input 框限定输入值为浮点型的js代码
2017/09/25 Javascript
vue中axios处理http发送请求的示例(Post和get)
2017/10/13 Javascript
Angular 5.0 来了! 有这些大变化
2017/11/15 Javascript
Vue多种方法实现表头和首列固定的示例代码
2018/02/02 Javascript
vue 子组件向父组件传值方法
2018/02/26 Javascript
vue移动端UI框架实现QQ侧边菜单组件
2018/03/09 Javascript
详解ES6通过WeakMap解决内存泄漏问题
2018/03/09 Javascript
Vue 中mixin 的用法详解
2018/04/23 Javascript
vue 实现单选框设置默认选中值
2019/11/07 Javascript
JS时间戳与日期格式互相转换的简单方法示例
2021/01/30 Javascript
Python操作csv文件实例详解
2017/07/31 Python
selenium在执行phantomjs的API并获取执行结果的方法
2018/12/17 Python
TensorFlow加载模型时出错的解决方式
2020/02/06 Python
在Pytorch中使用Mask R-CNN进行实例分割操作
2020/06/24 Python
CSS3选择器新增问题的实现
2021/01/21 HTML / CSS
英国综合网上购物商城:The Hut
2018/07/03 全球购物
学校七一活动方案
2014/01/19 职场文书
公司委托书格式范本
2014/09/16 职场文书
党的群众路线教育实践活动对照检查材料(教师)
2014/09/24 职场文书
2015年保险公司工作总结
2015/04/24 职场文书