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的Tornado框架异步编程入门实例
Apr 24 Python
Python按行读取文件的实现方法【小文件和大文件读取】
Sep 19 Python
python模块之time模块(实例讲解)
Sep 13 Python
Python中getpass模块无回显输入源码解析
Jan 11 Python
flask使用session保存登录状态及拦截未登录请求代码
Jan 19 Python
python调用Matplotlib绘制分布点并且添加标签
May 31 Python
Python2实现的图片文本识别功能详解
Jul 11 Python
Python 生成 -1~1 之间的随机数矩阵方法
Aug 04 Python
python实现石头剪刀布程序
Jan 20 Python
Tensorflow 卷积的梯度反向传播过程
Feb 10 Python
Python调用百度OCR实现图片文字识别的示例代码
Jul 17 Python
Python利用命名空间解析XML文档
Aug 10 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
PHP5中的this,self和parent关键字详解教程
2007/03/19 PHP
PHP 验证码的实现代码
2011/07/17 PHP
ThinkPHP框架中使用Memcached缓存数据的方法
2018/03/31 PHP
laravel5表单唯一验证的实例代码
2019/09/30 PHP
HTML node相关的一些资料整理
2010/01/01 Javascript
jQueryPad 实用的jQuery测试工具(支持IE,chrome,FF)
2010/05/22 Javascript
javascript常用的正则表达式实例
2014/05/15 Javascript
基于jQuery+JSON的省市二三级联动效果
2015/06/05 Javascript
基于dropdown.js实现的两款美观大气的二级导航菜单
2015/09/02 Javascript
微信小程序 wx.request(object) API详解及实例代码
2016/09/30 Javascript
Node.js中process模块常用的属性和方法
2016/12/13 Javascript
JavaScript实现父子dom同时绑定两个点击事件,一个用捕获,一个用冒泡时执行顺序的方法
2017/03/30 Javascript
Node.js开发第三方微信公众平台
2017/06/05 Javascript
利用vue + element实现表格分页和前端搜索的方法
2017/12/25 Javascript
JS开发 富文本编辑器TinyMCE详解
2019/07/19 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
2019/11/11 Javascript
JS自定义对象创建与简单使用方法示例
2020/01/15 Javascript
vue 路由懒加载中给 Webpack Chunks 命名的方法
2020/04/24 Javascript
[03:20]次级联赛厮杀超职业 现超级兵对拆世纪大战
2014/10/30 DOTA
web.py获取上传文件名的正确方法
2014/08/26 Python
python使用电子邮件模块smtplib的方法
2016/08/28 Python
django admin 后台实现三级联动的示例代码
2018/06/22 Python
python生成n个元素的全组合方法
2018/11/13 Python
Flask之pipenv虚拟环境的实现
2019/11/26 Python
Python绘制全球疫情变化地图的实例代码
2020/04/20 Python
Pycharm中如何关掉python console
2020/10/27 Python
PyQT5速成教程之Qt Designer介绍与入门
2020/11/02 Python
详解CSS的border边框属性及其在CSS3中的新特性
2016/05/10 HTML / CSS
Booking.com荷兰:全球酒店网上预订
2017/08/22 全球购物
巴西最大的玩具连锁店:Ri Happy
2020/06/17 全球购物
饭店工作计划书
2014/01/10 职场文书
生日礼品店创业计划书范文
2014/03/21 职场文书
促销活动总结模板
2014/07/01 职场文书
2014年医院科室工作总结
2014/12/20 职场文书
小鞋子观后感
2015/06/05 职场文书
springboot @ConfigurationProperties和@PropertySource的区别
2021/06/11 Java/Android