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 相关文章推荐
Python抓取Discuz!用户名脚本代码
Dec 30 Python
python实现得到一个给定类的虚函数
Sep 28 Python
python 远程统计文件代码分享
May 14 Python
python基于urllib实现按照百度音乐分类下载mp3的方法
May 25 Python
python使用xmlrpclib模块实现对百度google的ping功能
Jun 02 Python
python 实现删除文件或文件夹实例详解
Dec 04 Python
Python求离散序列导数的示例
Jul 10 Python
python使用writerows写csv文件产生多余空行的处理方法
Aug 01 Python
django 中使用DateTime常用的时间查询方式
Dec 03 Python
python列表推导和生成器表达式知识点总结
Jan 10 Python
python实现简单学生信息管理系统
Apr 09 Python
如何通过python计算圆周率PI
Nov 11 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
德生PL330的评价与改造
2021/03/02 无线电
PHP的开发框架的现状和展望
2007/03/16 PHP
用PHP写的MySQL数据库用户认证系统代码
2007/03/22 PHP
发款php蜘蛛统计插件只要有mysql就可用
2010/10/12 PHP
php正则过滤html标签、空格、换行符的代码(附说明)
2010/10/25 PHP
php学习笔记 面向对象的构造与析构方法
2011/06/13 PHP
php无限极分类实现的两种解决方法
2013/04/28 PHP
php使用 readfile() 函数设置文件大小大小的方法
2017/08/11 PHP
PHP+redis实现的限制抢购防止商品超发功能详解
2019/09/19 PHP
Laravel登录失败次数限制的实现方法
2020/08/26 PHP
JavaScript 监听textarea中按键事件
2009/10/08 Javascript
window.dialogArguments 使用说明
2011/04/11 Javascript
JavaScript控制各种浏览器全屏模式的方法、属性和事件介绍
2014/04/03 Javascript
对new functionName()定义一个函数的理解
2014/05/22 Javascript
node.js中的querystring.unescape方法使用说明
2014/12/10 Javascript
使用jquery菜单插件HoverTree仿京东无限级菜单
2014/12/18 Javascript
简单实现兼容各大浏览器的js复制内容到剪切板
2015/09/09 Javascript
jQuery实现简易的天天爱消除小游戏
2015/10/16 Javascript
浅谈javascript中执行环境(作用域)与作用域链
2016/12/08 Javascript
浅谈Vue下使用百度地图的简易方法
2018/03/23 Javascript
JS实现table表格内针对某列内容进行即时搜索筛选功能
2018/05/11 Javascript
webgl实现物体描边效果的方法介绍
2019/11/27 Javascript
nodejs脚本centos开机启动实操方法
2020/03/04 NodeJs
Python3.6.x中内置函数总结及讲解
2019/02/22 Python
详解tf.device()指定tensorflow运行的GPU或CPU设备实现
2021/02/20 Python
拉丁舞学习者的自我评价
2013/10/27 职场文书
毕业生就业自荐书
2013/12/15 职场文书
网络专业学生个人的自我评价
2013/12/16 职场文书
中文专业毕业生自荐信
2014/05/24 职场文书
优秀班组长事迹
2014/05/31 职场文书
小学数学课题方案
2014/06/15 职场文书
2014党员学习兰辉先进事迹思想汇报
2014/09/17 职场文书
骨干教师考核评语
2014/12/31 职场文书
水浒传读书笔记
2015/06/25 职场文书
学会感恩主题班会
2015/08/12 职场文书
python函数的两种嵌套方法使用
2022/04/02 Python