Python进阶学习之特殊方法实例详析


Posted in Python onDecember 01, 2017

前言

最近在学习python,学习到了一个之前没接触过的--特殊方法。

什么是特殊方法?当我们在设计一个类的时候,python中有一个用于初始化的方法$__init__$,类似于java中的构造器,这个就是特殊方法,也叫作魔术方法。简单来说,特殊方法可以给你设计的类加上一些神奇的特性,比如可以进行python原生的切片操作,迭代、连乘操作等。在python中,特殊方法以双下划线开始,以双下划线结束。

一个大例子

数学中有一个表示数的概念叫做向量,但是python中的数据类型却没有。我们来设法用python实现它。

首先考虑,向量跟普通的数据类型不同,传统的数可以直接进行运算,向量则需要对不同的坐标分别运算。来试试。

首先定义一个类,实现初始化方法。

# 实现向量类型
class Vector:
 
 def __init__(self, x=0, y=0):
  self.x = x
  self.y = y

如何实现向量的加法?二维向量中,向量的加法就是每个坐标分别相加得到的结果。在python中有个$__add__$方法,用来进行加法操作。

class Vector:
 
 def __init__(self, x=0, y=0):
  self.x = x
  self.y = y

 # 实现向量加法
 def __add__(self, other):
  x = self.x + other.x
  y = self.y + other.y
  return Vector(x, y)

我们对x和y变量分别进行相加,然后返回Vector。在python你可以对字符串直接用加法拼接起来的原理就在此,python实现了针对字符串的add方法。

实现了加法,乘法的道理一样,分别对每个坐标单独相乘即可。

class Vector:
 
 def __init__(self, x=0, y=0):
  self.x = x
  self.y = y

 # 实现向量加法
 def __add__(self, other):
  x = self.x + other.x
  y = self.y + other.y
  return Vector(x, y)
 
 # 实现向量乘法,例如r*3
 def __mul__(self, scalar):
  return Vector(self.x*scalar, self.y*scalar)

我们在进行向量运算时还有一个常用的操作是求向量的模,我们用$__abs__$特殊方法来实现,abs一般用来求一个数的绝对值,向量用不到,用来求模刚好合适。使用math模块中的hypot方法计算$\sqrt(x^2+y^2)$。

class Vector:
 
 def __init__(self, x=0, y=0):
  self.x = x
  self.y = y
 
 # 真假值,如果向量模为0,返回false
 def __bool__(self):
  return bool(abs(self))

 # 实现向量加法
 def __add__(self, other):
  x = self.x + other.x
  y = self.y + other.y
  return Vector(x, y)
 
 # 实现向量乘法,例如r*3
 def __mul__(self, scalar):
  return Vector(self.x*scalar, self.y*scalar)

 
 # 返回向量的模
 # hypot()返回欧几里德范数 sqrt(x*x + y*y)
 def __abs__(self):
  return hypot(self.x, self.y)

找个例子运行下。

v = Vector(2, 3)
print(v)
v2 = Vector(4, 5)
print(v+v2)
print(v+v2*2)
<__main__.Vector object at 0x000002B4B1843C50>
<__main__.Vector object at 0x000002B4B1843EF0>
<__main__.Vector object at 0x000002B4B1843898>

可以运行了,貌似是正确的,但是输出的结果很奇怪。怎么办?python中有个$__repr__$特殊方法,可以修改控制台输出的样式。

class Vector:
 
 def __init__(self, x=0, y=0):
  self.x = x
  self.y = y
 
 # 真假值,如果向量模为0,返回false
 def __bool__(self):
  return bool(abs(self))

 # 实现向量加法
 def __add__(self, other):
  x = self.x + other.x
  y = self.y + other.y
  return Vector(x, y)
 
 # 实现向量乘法,例如r*3
 def __mul__(self, scalar):
  return Vector(self.x*scalar, self.y*scalar)
 
 # 返回向量的模
 # hypot()返回欧几里德范数 sqrt(x*x + y*y)
 def __abs__(self):
  return hypot(self.x, self.y)
 
 # 实现__repr__方法,在控制台打印向量时会输出Vector(1, 2)
 # 实现__str__,使用str()返回字符串
 def __repr__(self):
  return 'Vector(%r, %r)' % (self.x, self.y)

实现了$__repr__$方法,我们就可以在控制台输出Vecotor(x,y)。与之对应的有个$__str__$方法,使用str()返回相应的字符串,展示给用户。

现在来看下之前程序运行的结果。

v = Vector(2, 3)
print(v)
v2 = Vector(4, 5)
print(v+v2)
print(v+v2*2)
print(abs(v))
Vector(2, 3)
Vector(6, 8)
Vector(10, 13)
3.605551275463989

效果不错。

通过实现特殊方法,自定义类型可以表现的跟内置类型一样,让我们能够写出更具有python风格的代码。

除了上面说到的几个特殊方法外,python还有差不多80多个特殊方法,比如$__len__$方法可以用来求长度,$__getitem__$可以使用haha[2]之类的操作进行切片和迭代等,同样的还有$__setitem__$。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python新手入门最容易犯的错误总结
Apr 24 Python
浅析python3字符串格式化format()函数的简单用法
Dec 07 Python
python从子线程中获得返回值的方法
Jan 30 Python
利用django+wechat-python-sdk 创建微信服务器接入的方法
Feb 20 Python
python 判断linux进程,并杀死进程的实现方法
Jul 01 Python
python实现超市商品销售管理系统
Oct 25 Python
执行Python程序时模块报错问题
Mar 26 Python
Python脚本如何在bilibili中查找弹幕发送者
Jun 04 Python
解决Keyerror ''acc'' KeyError: ''val_acc''问题
Jun 18 Python
解决Keras中Embedding层masking与Concatenate层不可调和的问题
Jun 18 Python
python爬虫selenium模块详解
Mar 30 Python
python数字类型和占位符详情
Mar 13 Python
Python用户推荐系统曼哈顿算法实现完整代码
Dec 01 #Python
浅谈python 里面的单下划线与双下划线的区别
Dec 01 #Python
vscode 远程调试python的方法
Dec 01 #Python
Python中单、双下划线的区别总结
Dec 01 #Python
从CentOS安装完成到生成词云python的实例
Dec 01 #Python
Django的分页器实例(paginator)
Dec 01 #Python
浅谈python装饰器探究与参数的领取
Dec 01 #Python
You might like
php下mysql数据库操作类(改自discuz)
2010/07/03 PHP
通过修改配置真正解决php文件上传大小限制问题(nginx+php)
2015/09/23 PHP
[原创]CI(CodeIgniter)简单统计访问人数实现方法
2016/01/19 PHP
php使用SAE原生Mail类实现各种类型邮件发送的方法
2016/10/10 PHP
php 中奖概率算法实现代码
2017/01/25 PHP
幻宇的层模拟窗口效果-提供演示和下载
2007/01/20 Javascript
jquery select选中的一个小问题
2009/10/11 Javascript
为原生js Array增加each方法
2012/04/07 Javascript
jquery 取子节点及当前节点属性值
2014/07/25 Javascript
微信中一些常用的js方法汇总
2015/03/12 Javascript
jQuery实现网页顶部固定导航效果代码
2015/12/24 Javascript
Vue.js报错Failed to resolve filter问题的解决方法
2016/05/25 Javascript
JavaScript九九乘法口诀表的简单实现
2016/10/04 Javascript
JS实现禁止鼠标右键的功能
2016/10/15 Javascript
JS实现的Unicode编码转换操作示例
2017/04/28 Javascript
JS实现静态页面搜索并高亮显示功能完整示例
2017/09/19 Javascript
Vue实现搜索 和新闻列表功能简单范例
2018/03/16 Javascript
解决Layui 表格自适应高度的问题
2019/11/15 Javascript
vue 实现click同时传入事件对象和自定义参数
2021/01/29 Vue.js
Python实现过滤单个Android程序日志脚本分享
2015/01/16 Python
python素数筛选法浅析
2018/03/19 Python
python实现linux下抓包并存库功能
2018/07/18 Python
Python PyQt5 Pycharm 环境搭建及配置详解(图文教程)
2019/07/16 Python
python中Mako库实例用法
2020/12/31 Python
利用CSS3伪元素实现逐渐发光的方格边框
2017/05/07 HTML / CSS
HTML 5.1来了 9月份正式发布 更新内容预览
2016/04/26 HTML / CSS
打造经典复古风格的品牌:Alice + Olivia(爱丽丝+奥利维亚)
2016/09/07 全球购物
后勤主管工作职责
2013/12/07 职场文书
电厂厂长岗位职责
2014/01/02 职场文书
大型会议接待方案
2014/03/01 职场文书
《记金华的双龙洞》教学反思
2014/04/19 职场文书
保证金退回承诺函格式
2015/01/21 职场文书
2015年国庆节寄语
2015/08/17 职场文书
公务员岗前培训心得体会
2016/01/08 职场文书
公文写作指导之倡议书!
2019/07/03 职场文书
Vue实现动态查询规则生成组件
2021/05/27 Vue.js