Python中类的初始化特殊方法


Posted in Python onDecember 01, 2017

什么是特殊方法?当我们在设计一个类的时候,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 相关文章推荐
windows下Python实现将pdf文件转化为png格式图片的方法
Jul 21 Python
Python编程之gui程序实现简单文件浏览器代码
Dec 08 Python
Python KMeans聚类问题分析
Feb 23 Python
Python 实现选择排序的算法步骤
Apr 22 Python
对Python字符串中的换行符和制表符介绍
May 03 Python
解决phantomjs截图失败,phantom.exit位置的问题
May 17 Python
Python运维之获取系统CPU信息的实现方法
Jun 11 Python
python寻找list中最大值、最小值并返回其所在位置的方法
Jun 27 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
May 10 Python
Python使用正则表达式分割字符串的实现方法
Jul 16 Python
通过字符串导入 Python 模块的方法详解
Oct 27 Python
Python代码注释规范代码实例解析
Aug 14 Python
Python抓取框架Scrapy爬虫入门:页面提取
Dec 01 #Python
Python实现调度算法代码详解
Dec 01 #Python
Python进阶学习之特殊方法实例详析
Dec 01 #Python
Python用户推荐系统曼哈顿算法实现完整代码
Dec 01 #Python
浅谈python 里面的单下划线与双下划线的区别
Dec 01 #Python
vscode 远程调试python的方法
Dec 01 #Python
Python中单、双下划线的区别总结
Dec 01 #Python
You might like
使用 php4 加速 web 传输
2006/10/09 PHP
PHP+FLASH实现上传文件进度条相关文件 下载
2007/07/21 PHP
php强制用户转向www域名的方法
2015/06/19 PHP
非常全面的php日期时间运算汇总
2015/11/04 PHP
php bootstrap实现简单登录
2016/03/08 PHP
PHP中addslashes与mysql_escape_string的区别分析
2016/04/25 PHP
PHP实现的mysql读写分离操作示例
2018/05/22 PHP
解决php extension 加载顺序问题
2019/08/16 PHP
使用PHP+Redis实现延迟任务,实现自动取消订单功能
2019/11/21 PHP
nodejs实现的一个简单聊天室功能分享
2014/12/06 NodeJs
jQuery插件Timelinr 实现时间轴特效
2015/10/04 Javascript
Javascript 事件冒泡机制详细介绍
2016/10/10 Javascript
Bootstrap基本组件学习笔记之按钮组(8)
2016/12/07 Javascript
D3.js进阶系列之CSV表格文件的读取详解
2017/06/06 Javascript
vue实现一个移动端屏蔽滑动的遮罩层实例
2017/06/08 Javascript
nodejs+mongodb+vue前后台配置ueditor的示例代码
2018/01/02 NodeJs
vue.js实现三级菜单效果
2019/10/19 Javascript
Vue Elenent实现表格相同数据列合并
2020/11/30 Vue.js
js实现滚动条自动滚动
2020/12/13 Javascript
状态机的概念和在Python下使用状态机的教程
2015/04/11 Python
用Python编写简单的定时器的方法
2015/05/02 Python
简单谈谈Python的pycurl模块
2018/04/07 Python
基于python的BP神经网络及异或实现过程解析
2019/09/30 Python
解决os.path.isdir() 判断文件夹却返回false的问题
2019/11/29 Python
浅谈tensorflow之内存暴涨问题
2020/02/05 Python
Opencv常见图像格式Data Type及代码实例
2020/11/02 Python
Expedia法国:全球最大在线旅游公司
2018/09/30 全球购物
JAVA和C++区别都有哪些
2015/03/30 面试题
刑事辩护授权委托书
2014/09/13 职场文书
乡镇遵守党的政治纪律情况对照检查材料
2014/09/26 职场文书
科学育儿宣传标语
2014/10/08 职场文书
2015年元旦联欢晚会活动总结
2014/11/28 职场文书
募捐感谢信
2015/01/22 职场文书
试用期解除劳动合同通知书
2015/04/16 职场文书
消防宣传标语大全
2015/08/03 职场文书
Go遍历struct,map,slice的实现
2021/06/13 Golang