python中存在一些特殊的方法,这些方法通常采用格式:__method__()。这些方法会在特定的情况下自动调用。例如:__new__()、__init__()、__del__() 等生命周期方法。正是这些特殊方法,构建了python的语言风格。特殊方法有很多,比如下面列出来的这些,我们按照类别研究其中的一部分。其他的等到真的用到的再往上加吧。

python中的魔术方法

我们先来看看这些特殊方法有什么用,它作了什么简化,一般在实际情况下我们什么时候才会使用到这些方法。

假设有一个表示在线订单的类,具有购物车 (列表) 和顾客 (代表顾客的str或其他类的实例)两种数据。

在这种情况下,要获得购物车列表的长度是很自然的。新接触 Python 的人可能会选择在他们的类中实现一个叫get_cart_len()的方法来执行此项。但是,你也可以重载内置函数len(),以便在给定对象时返回购物车列表的长度。

在另一种情况下, 我们可能需要添加一些东西到购物车。再次,新接触 Python 的人会想到实现一个append_to_cart()方法,以添加东西到购物车列表。但是你也可以配置运算符+,用它来将新内容添加到购物车中。

Python 使用特殊的方法来做这些。这些特殊方法具有命名约定,其中名称以两个下划线开头, 后跟一个标识符, 并以另一对下划线结尾。(就是我们说的魔术方法啦)

本质上, 每个内置函数或运算符都有一个与之对应的特殊方法。例如,对应于 len()有__len__(),对应于运算符 + 有__add__()。

默认情况下, 大多数内置函数和运算符都不能与自定义类的对象一起使用。必须在类定义中添加相应的特殊方法,才能使对象与内置和运算符兼容。这就是我们接下来要讨论的 python 运算符重载。

执行此操作时,与其关联的函数或运算符的行为将根据方法中定义的方式进行更改。

在说运算符重载之前,我们来看一下魔术方法的特点:(敲黑板儿)

特殊方法定义在class中

不需要直接调用

python的某些函数或操作符会调用相应的特殊方法

运算符重载

目的:让自定义的类生成的对象(实例)能够使用运算符进行操作。依据运算数据的不同,为运算符定义不同的行为。

作用(好处):

让自定义的实例像内建对象一样进行运算符操作,令用户定义的对象能够使用中缀运算符(如 + 和 | )或一元运算符(如 - 和 ~ )等运算符。

让程序简洁易读;

对自定义对象将运算符赋予新的规则。

我们知道,数据类型 = 数据结构 + 运算 ,有了运算符重载意味着我们可以定义自己的数据类型了。

为了做好灵活性、可用性和安全性方面的平衡,Python对运算符重载施加了一些限制:

不能重载内置类型的运算符;

不能新建运算符,只能重载现有运算符;

某些运算符不能重载,如is、and、or和not(不过位运算符&、| 和 ~可以)。

下面我们来看一个例子:二维向量类的加法。(这个例子太经典啦哈哈哈)

假设有Vector2D类代表一个二维向量。我们知道Vector2D(3,4) + Vector2D(1,1) = Vector2D(4,5),我们通过重载魔术方法__add__来实现这一功能。

class Vector2D:

def __init__(self, x, y):

self.x = x

self.y = y

def __add__(self, other):

x = self.x + other.x

y = self.y +other.y

return Vector2D(x, y)

def __str__(self):

return "Vector2D(x={}, y={})".format(self.x, self.y)

v1 = Vector2D(1, 2)

v2 = Vector2D(3, 4)

v3 = v1 + v2

print(v3)

Vector2D(x=4, y=6)

结果是正确的,我们并没有调用__add__而是直接使用 + 就可以啦,还记得之前我们说过的魔术方法的特点吗?

当我们在重载双目运算符的时候,会多传入一个参数other。

在上面的例子中我们还重载了一个特殊方法__str__, 我们下面会介绍这个方法, 这个方法通过 print() 函数调用。

接下来我们在重载一些其他的运算:

from math import hypot,sqrt

class Vector:

def __init__(self, x, y):

self.x = x

self.y = y

#__str__方法,会在打印变量时,自动调用

def __str__(self):

return 'Vector(%r,%r)' %(self.x, self.y)

#__abs__函数会在调用abs()函数时,自动调用

def __abs__(self):

#hypot(x,y) 返回欧几里得范数 sqrt(x*x + y*y)

return hypot(self.x, self.y)

#__bool__函数会在调用bool()函数时,自动调用

def __bool__(self):

return bool(abs(self))

# 执行a + b时,自动调用

def __add__(self, other):

x = self.x + other.x

y = self.y + other.y

return Vector(x,y)

# 执行a+=b时,自动调用

def __iadd__(self, other):

return self + other

# 执a * b的时候,会自动调用

def __mul__(self, scalar):

return Vector(self.x * scalar,self.y * scalar)

# 求-a时,自动调用

def __neg__(self):

return Vector(-self.x,-self.y)

def __matmul__():

pass

v1 = Vector(2,4)

v2 = Vector(2,1)

print(v1 + v2)

v = Vector(3,4)

print(abs(v))

print(v * 3)

print(abs(v * 3))

print(-v)

v1 += v2

print(v1)

Vector(4,5)

5.0

Vector(9,12)

15.0

Vector(-3,-4)

Vector(4,5)

在上面我们实现了自加操作,(+=)实际上因为我们实现了 + 操作,解释器会自动实现这个方法。

值得注意的是反向操作,如果你了解 Matlab 一定知道Matlab有左除与右除。python也有类似的用法。我们以加法为例:辨析 __add__()与__radd__()的不同.

先看一个例子:

class A:

def __add__(self, other):

print('A add')

def __radd__(self, other):

print('B add')

class B:

pass

if __name__ == "__main__":

a = A()

b = B()

a + b

b + a

A add

B add

在这个例子中,在b + a 时b没有实现加法操作,那么解释器就调用了,a 的反向方法。

执行a + b 的流程如下:

如果a有__add__方法,而且返回值不是NotImplemented,调用a.__add__(b),然后返回结果。

如果a没有__add__方法,或者调用__add__方法返回NotImplemented,检查b有没有__radd__方法,如果有,而且没有返回NotImplemented,调用b.__radd__(a),然后返回结果。

如果b没有__radd__方法,或者调用__radd__方法返回NotImplemented,抛出TypeError,并在错误消息中指明操作数类型不支持。

常见的运算符重载方法

中缀运算符

python次方运算_neg__python 魔术方法1 运算符重载相关推荐

  1. 92_特殊方法(魔术方法)和运算符重载

    96.特殊方法(魔术方法)和运算符重载 python - 特殊方法查找-文档1 python - 特殊方法-文档2 Python的运算符实际上是通过调用对象的特殊方法实现的.比如: 测试代码1 a = ...

  2. (转)python类:magic魔术方法

    原文:https://blog.csdn.net/pipisorry/article/details/50708812 版权声明:本文为博主皮皮http://blog.csdn.net/pipisor ...

  3. Python世界里的魔术方法(一)

    序言 传说中,Python对象天生具有一些神奇的方法,它们具有一些魔力,因此它们总被双下划线所包围着.这些方法统称为魔术方法.在特定的操作下,这些魔术方法会被自动调用,并且表现出许多神奇的现象. 它们 ...

  4. Python中最全魔术方法整理

    Python中的魔术方法 所谓魔法函数(Magic Methods),是Python的一种高级语法,允许你在类中自定义函数,并绑定到类的特殊方法中.比如在类A中自定义__str__()函数,则在调用s ...

  5. 27、Python 面向对象(创建类、创建实例对象、访问属性、内置类属性、对象销毁、类的继承、方法重写、基础重载方法、运算符重载、类属性与方法、下划线双下划线)

    27Python面向对象(Python2) Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. ...

  6. Python的面向对象,魔术方法、类的三大特征、自省、实例空间、经典类与新式类

    目录 1.什么是面向对象 1.1 面向过程 1.2 面向对象 1.3 面向对象的优点 2.类 2.1 什么是类.对象,方法和属性 2.2 类的定义和使用 2.2.1 类名规范和类的写法 2.3 魔术方 ...

  7. python进阶1:魔术方法

    1.定义 在类里面,使用__xx__()形式的方法.这一类方法可以在类被构建的时候隐式调用,从而实现多种功能.也可以通过重载这些魔术方法,来实现自定义的功能. 2.常用的魔术方法 2.1 __new_ ...

  8. Python学习手册之内部方法、操作符重载和对象生命周期

    在上一篇文章中,我们介绍了 Python 的类和继承,现在我们介绍 Python 的内部方法.操作符重载和对象生命周期. 查看上一篇文章请点击:https://www.cnblogs.com/dust ...

  9. Python-特殊方法(迭代器,生成器,内建方法,运算符重载)

    Python是一门独特的语言,力求简洁,它甚至不像某些语言(如Java)提供接口语法,Python语言采用的是"约定"规则,它提供了大量具有特殊意义的方法,这些方法有些可以直接使用 ...

最新文章

  1. range函数python循环次数查询_python进阶教程之循环相关函数range、enumerate、zip
  2. R语言-包的安装、载入及使用方法
  3. python批量读取文件内容_Python 文本文件内容批量抽取实例
  4. 基于SSM实现汽车租赁系统
  5. 最新 Windows 7 7100安装
  6. UVa563 - Crimewave
  7. collections 中的namedtuple
  8. 3 分钟了解 JSON Schema
  9. 关闭mysql方法_启动和关闭MySQL的方法
  10. NIPS不改名再引风波:签名抗议活动开启,大咖纷纷发声支持
  11. vue2.0 组件和v-model
  12. 7. Simple Product
  13. ubuntu运行c/c++语言
  14. matlab拟合心得体会,Matlab数据拟合工具在数学建模中的简单应用
  15. matlab数值拟合r2_MATLAB数据拟合实例(给出两组数据拟合y=ax±b).doc
  16. 错误:java 找不到符号
  17. [CSDN] 微软雅黑可能导致的博客侵权问题
  18. 投资理财——如何选择基金
  19. 在堆区开辟内存(动态内存的开辟)
  20. 869计算机难不难,北京科技大学

热门文章

  1. linux基础知识——wait函数和waitpid函数回收子进程
  2. JSP页面元素,内置对象及request详解
  3. Leetcode--141. 环形链表
  4. sql server如何输出排序序号_Group by中子查询order by排序失效问题分析
  5. dir结构体 linux_Linux下DIR,dirent,stat等结构体详解
  6. python快速入门课堂笔记_Python 快速入门笔记(9):模块和包
  7. idea2019配置gradle详解_Constraint Layout 2.0 用法详解
  8. TypeError: 'numpy.int64' object is not iterable ,'int' object is not iterable
  9. TensorFlow实现单隐层神经网络
  10. 怎样把MySQL的编码方式改为utf8?