本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理

一种运算符对于不同类型的对象,有不同的使用方式。例如, + 用于整型对象,表示两个数相加;用于字符串,表示连接这两个字符串。

x, y = 10, 20
print(x + y) # 30 a,b = 'John', 'Wick'
print(a + b) # John Wick
复制代码

**+**运算符因操作对象的类型的不同而执行不同的操作,这种特性称为重载。

运算符的功能因其操作数据的类型而异,我们称之为重载。

+运算符可以用于任意两个对象的相加吗?我们来试试看。

class Vector:
def __init__(self, x, y):
self.x = x
self.y = y v1 = Vector(3, 4)
v2 = Vector(5, 6)
v1 + v2 ---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-08104d7e1232> in <module>
----> 1 v1 + v2 TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector'
复制代码

运行这段代码会报错。为什么呢?这是因为 + 运算符不知道如何把两个 Vector 类的对象相加。

在本文中,我们将研究如何将既有的运算符用于自定义对象的操作,同时我们要牢记 Python 语言对操作符重载的一些限制性规则。

这些限制性规则有:

  1. 不允许创建新的运算符,只能重载已有的那些运算符
  2. 不允许重载已有数据类型(如 tuple 、 string 、 list)的某些运算符操作
  3. 某些运算符不能重载,例如 is, or, and, not

在开始学习运算符重载前,我们需要了解 Python 数据模型 和 特殊方法。

Python 数据模型可以看作一种 “Python 设计方式”或 “Python 框架”。它告诉你 Python 如何管理对象以及如何对它们进行操作。它描述了一系列 API,你可以使用这些 API 使你定义的对象具备已有数据类型的某些功能,并且可以使用大多数 Python 语言的特性,而且不必实现它们。

特殊方法 → 当你使用 len(collection),Python 解释器调用的是 collection.len() 方法。这里的 len() 就是一个特殊方法。

特殊方法开头和结尾都是 __ ,意为只能由 Python 解释器调用,除非你在进行元编程,不然不要直接调用它。

在 Python 语言中,我们可以使用特殊方法来实现运算符重载。

现在我们进行编码,使 Vector 对象支持 + 运算符。

当我们调用 **+** 这个运算符时,Python 解释器调用了 add(self, other) 这个特殊方法。所以,在我们定义的类中实现 add() 方法,就可以支持 + 运算符。

class Vector:
def __init__(self, x, y):
self.x = x
self.y = y def __add__(self, other):
return Vector(self.x + other.x , self.y + other.y) def __repr__(self):
return f'Vector({self.x}, {self.y})' v1 = Vector(3, 4)
v2 = Vector(5, 6)
v1 + v2
>>> Output: Vector(8, 10)
复制代码

你会发现,我们的类已经支持 + 运算符,在这个类中还实现了 repr() 方法,当我们调用 print() 方法,解释器调用 str() 方法,如果我们没有提供 repr() 的实现,就会调用原来的 repr() 方法。

注意:除了重载类似于 += 的赋值运算符外,一定要返回一个新建的对象。

再举个重载运算符的例子

当我们使用 **==** 运算符时,Python 解释器会调用 eq(self, other) 这个特殊方法,所以我们通过实现 eq() 方法就可以使某个类支持 == 运算符。

class Vector:
def __init__(self, x, y):
self.x = x
self.y = y def __add__(self, other):
return Vector(self.x + other.x , self.y + other.y) def __repr__(self):
return f'Vector({self.x}, {self.y})' def __eq__(self, other):
return self.x == other.x and self.y == other.y v1 = Vector(3, 4)
v2 = Vector(5, 6)
v1 == v2
>>> Output: False v3 = Vector(3,4)
v1 == v3
>>> Output: True
复制代码

在 Python 中,使用特殊方法可以轻松实现运算符重载。关键在于理解数据模型和特殊方法。

这些方法能让你从 Python 的惯用特性中受益,并且能利用强大的标准库。

欲了解 Python 数据模型的更多详情,请参考 Fluent python。

这里是 Python 中的特殊方法汇总,可供查阅。

总结

我们从理解什么是运算符重载开始,接着讨论了 Python 中运算符重载的一些限制条件、数据模型和特殊方法,然后在 Vector 类中实现了运算符重载。

希望你喜欢这篇文章。祝你工作顺利,好运连连!

想要获取更多Python学习资料可以加
QQ:2955637827私聊
或加Q群630390733
大家一起来学习讨论吧!

Python 中的运算符重载的更多相关文章

  1. C++中的运算符重载注意事项

    1.C++中的运算符重载的方式有三种: a.类成员函数重载 b.友元函数重载 c.普通函数重载 注意: a.我们主要使用的方式主要是用:类成员函数和友元函数来实现运算符的重载. b.其实用普通函数理论 ...

  2. 【Python】 解析Python中的运算符

    Python中的运算符相比较于传统的C/C++差别不是很大,主要是一些个别的运算符上的差别.包括:算术.比较.赋值.位.逻辑.成员.身份等.它们的优先级: 符号 说明 ** 指数(最高优先级) ~,+ ...

  3. 【转】Python中的运算符

    [转]Python中的运算符 说完常用的数据类型,再来说下运算符.运算符用于将各种类型的数据进行运算,让静态的数据跑起来. 编程语言中的运算大致分为以下几个大类: 算术运算, 用于加减乘除等数学运算 ...

  4. python中的运算符及表达式及常用内置函数

    知识内容: 1.运算符与表达式 2.for\while初步了解 3.常用内置函数 一.运算符与表达式 python与其他语言一样支持大多数算数运算符.关系运算符.逻辑运算符以及位运算符,并且有和大多数 ...

  5. c++中的运算符重载operator2(翁恺c++公开课[31-33]学习笔记)

    上一篇operator1中,大概说了下重载的基本用法,接下来对c++中常见的可重载运算符归一下类,说一下它们的返回值,讨论下较为复杂的运算符重载上的坑

  6. c++中的运算符重载operator1(翁恺c++公开课[30]学习笔记)

    运算符重载规则: 只有已经存在的运算符才能被重载,不能自己制造一个c++中没有的运算符进行重载 重载可以在类或枚举类型内进行,也可以是全局函数,但int.float这种已有的类型内是不被允许的 不能二 ...

  7. C++走向远洋——50(Time类中的运算符重载、一目,二目比较运算符、二目赋值运算符、二目加减法运算符)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  8. C++走向远洋——49(项目一2、复数类中的运算符重载、类的友元函数)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  9. C++走向远洋——48(项目一1、复数类中的运算符重载、类的成员函数)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

随机推荐

  1. C++基础入门知识:C++命名空间(名字空间)详解

    一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量或函数的命名冲突.当所有人的代码都测试通过,没有问题时,将它们结合到一起就有可能会出现命名冲突. 例如小李和小韩都参 ...

  2. 【mq读书笔记】消息消费队列和索引文件的更新

    ConsumeQueue,IndexFile需要及时更新,否则无法及时被消费,根据消息属性查找消息也会出现较大延迟. mq通过开启一个线程ReputMessageService来准时转发commitL ...

  3. 推荐:国产etl调度工具Taskctl web应用版,0元永久授权

    写在前面 2020年疫情席卷全球,更是对整个市场经济造成了严重影响,年初疫情肆虐,西方世界单方面的科技.经济封锁,国际关系吃紧.....导致很多中小型企业业务链受阻,大型企业经费资金吃紧,轮班制导致公 ...

  4. python应用(6):函数

    在流程很简单的时候,或者流程不简单但我们不需要考虑开发维护成本的时候,平面地组织你的代码就够了,不用费脑子,不需要考虑层次或重用的东西.当事情变得越来越复杂时,当同行对代码质量要求越来越高时,有一些重 ...

  5. 老猿学5G随笔:5G的三大业务场景eMBB、URLLC、mMTC

    5G的三大业务场景eMBB.URLLC.mMTC: eMBB:英文全称Enhanced Mobile Broadband,即增强移动宽带,是利用5G更好的网络覆盖及更高的传输速率来为用户提供更好的上网 ...

  6. PyQt学习随笔:自定义信号连接时报AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 如果使用自定义信号,一定要记得信号是类变量,必须在类中定义,不能在实例 ...

  7. 利用flask框架实现对用户的注册登录

    ------------------------------------(分割线)----------------------------------------------------------- ...

  8. 使用k8s部署springboot+redis简单应用

    准备 本文将使用k8s部署一个springboot+redis应用,由于是示例,所以功能比较简单,只有设置值和获取值两个api. (1)设置值 (2)获取值 构建Web应用 (1)创建一个spring ...

  9. jQuery笔记(一)

    day01 - jQuery 学习目标: 能够说出什么是 jQuery 能够说出 jQuery 的优点 能够简单使用 jQuery 能够说出 DOM 对象和 jQuery 对象的区别 能够写出常用的 ...

  10. MySQL必知必会详细总结

    一.检索数据 1.检索单个列:SELECT prod_name FROM products; 2.检索多个列:SELECT prod_id,prod_name,prod_price FROM prod ...