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实现人人网登录示例分享
Jan 19 Python
python3设计模式之简单工厂模式
Oct 17 Python
python多进程中的内存复制(实例讲解)
Jan 05 Python
python实现字符串中字符分类及个数统计
Sep 28 Python
python反编译学习之字节码详解
May 19 Python
pandas数据筛选和csv操作的实现方法
Jul 02 Python
python3连接MySQL8.0的两种方式
Feb 17 Python
python如何更新包
Jun 11 Python
在 Windows 下搭建高效的 django 开发环境的详细教程
Jul 27 Python
Python非单向递归函数如何返回全部结果
Dec 18 Python
Python实现科学占卜 让视频自动打码
Apr 09 Python
Python Django / Flask如何使用Elasticsearch
Apr 19 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
深入file_get_contents与curl函数的详解
2013/06/25 PHP
关于PHP的curl开启问题探讨
2014/04/08 PHP
php基于双向循环队列实现历史记录的前进后退等功能
2015/08/08 PHP
php 中的closure用法详解
2017/06/12 PHP
PHP实现财务审核通过后返现金额到客户的功能
2019/07/04 PHP
十个优秀的Ajax/Javascript实例网站收集
2010/03/31 Javascript
js 获取class的元素的方法 以及创建方法getElementsByClassName
2013/03/11 Javascript
JavaScript中的typeof操作符用法实例
2014/04/05 Javascript
angularjs基础教程
2014/12/25 Javascript
javascript限制文本框输入值类型的方法
2015/05/07 Javascript
如何解决IONIC页面底部被遮住无法向上滚动问题
2016/09/06 Javascript
微信js-sdk分享功能接口常用逻辑封装示例
2016/10/13 Javascript
javascript判断元素存在和判断元素存在于实时的dom中的方法
2017/01/17 Javascript
基于jQuery选择器之表单对象属性筛选选择器的实例
2017/09/19 jQuery
Element-UI Table组件上添加列拖拽效果实现方法
2018/04/14 Javascript
nodejs中request库使用HTTPS代理的方法
2019/04/30 NodeJs
详解mpvue实现对苹果X安全区域的适配
2019/07/31 Javascript
layui+jquery支持IE8的表格分页方法
2019/09/28 jQuery
python引用DLL文件的方法
2015/05/11 Python
Python爬虫使用Selenium+PhantomJS抓取Ajax和动态HTML内容
2018/02/23 Python
Python函数装饰器实现方法详解
2018/12/22 Python
Python数据可视化教程之Matplotlib实现各种图表实例
2019/01/13 Python
使用pytorch实现论文中的unet网络
2020/06/24 Python
给Django Admin添加验证码和多次登录尝试限制的实现
2020/07/26 Python
python 用struct模块解决黏包问题
2020/11/07 Python
python 发送get请求接口详解
2020/11/17 Python
使用HTML5在网页中嵌入音频和视频播放的基本方法
2016/02/22 HTML / CSS
Whistles官网:英国女装品牌
2020/08/14 全球购物
HttpServlet类中的主要方法都有哪些?各自的作用是什么?
2014/03/16 面试题
药学专业大学生个人的自我评价
2013/11/04 职场文书
妇科医生自荐信
2013/11/05 职场文书
校本教研工作方案
2014/01/14 职场文书
网络营销策划方案
2014/06/04 职场文书
幼儿园安全责任书范本
2014/07/24 职场文书
python关于集合的知识案例详解
2021/05/30 Python
JavaScript如何优化逻辑判断代码详解
2021/06/08 Javascript