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中使用异常处理来判断运行的操作系统平台方法
Jan 22 Python
python 表达式和语句及for、while循环练习实例
Jul 07 Python
用Python删除本地目录下某一时间点之前创建的所有文件的实例
Dec 14 Python
python中datetime模块中strftime/strptime函数的使用
Jul 03 Python
Linux下Python安装完成后使用pip命令的详细教程
Nov 22 Python
python Pandas如何对数据集随机抽样
Jul 29 Python
python批量修改ssh密码的实现
Aug 08 Python
使用Python给头像加上圣诞帽或圣诞老人小图标附源码
Dec 25 Python
scrapy数据存储在mysql数据库的两种方式(同步和异步)
Feb 18 Python
python导入库的具体方法
Jun 18 Python
解决keras使用cov1D函数的输入问题
Jun 29 Python
Python实现提取PDF简历信息并存入Excel
Apr 02 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 删除一个数组中的某个值.兼容多维数组!
2012/02/18 PHP
ecshop实现smtp发送邮件
2015/02/03 PHP
微信公众号开发客服接口实例代码
2016/10/21 PHP
详解JavaScript函数绑定
2013/08/18 Javascript
IE下使用jQuery重置iframe地址时内存泄露问题解决办法
2015/02/05 Javascript
学习JavaScript设计模式之中介者模式
2016/01/14 Javascript
Vue.js计算属性computed与watch(5)
2016/12/09 Javascript
JavaScript验证知识整理
2017/03/24 Javascript
vue-resource 拦截器(interceptor)的使用详解
2017/07/04 Javascript
bootstrap table服务端实现分页效果
2017/08/10 Javascript
关于meta viewport中target-densitydpi属性详解(推荐)
2017/08/18 Javascript
Vue2.0用 watch 观察 prop 变化(不触发)
2017/09/08 Javascript
Vue v2.5 调整和更新不完全问题
2017/10/24 Javascript
javascript中关于类型判断的一些疑惑小结
2018/10/14 Javascript
jQuery实现的卷帘门滑入滑出效果【案例】
2019/02/18 jQuery
小程序调用微信支付的方法
2019/09/26 Javascript
vue实现打地鼠小游戏
2020/08/21 Javascript
理解JavaScript中的对象
2020/08/25 Javascript
vue中实现点击变成全屏的多种方法
2020/09/27 Javascript
[50:21]Liquid vs Winstrike 2018国际邀请赛小组赛BO2 第二场
2018/08/19 DOTA
[42:20]Secret vs Liquid 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
在Python中进行自动化单元测试的教程
2015/04/15 Python
python获取本机所有IP地址的方法
2018/12/26 Python
详解python多线程之间的同步(一)
2019/04/03 Python
Python3中_(下划线)和__(双下划线)的用途和区别
2019/04/26 Python
Python如何使用bokeh包和geojson数据绘制地图
2020/03/21 Python
Django限制API访问频率常用方法解析
2020/10/12 Python
Python文件名匹配与文件复制的实现
2020/12/11 Python
使用CSS3实现SVG路径描边动画效果入门教程
2019/10/21 HTML / CSS
Omio西班牙:全欧洲低价大巴、火车和航班搜索和比价
2017/02/11 全球购物
PHP如何去执行一个SQL语句
2016/03/05 面试题
园林设计专业毕业生求职信
2014/03/23 职场文书
2015年端午节活动方案
2015/05/05 职场文书
幼儿园音乐教学反思
2016/02/18 职场文书
Python中X[:,0]和X[:,1]的用法
2021/05/10 Python
SpringBoot中使用Redis作为全局锁示例过程
2022/03/24 Java/Android