首页 > 编程语言 >【Python】笔记:正确重载运算符

【Python】笔记:正确重载运算符

时间:2022-12-03 21:22:21浏览次数:58  
标签:__ return Python self 运算符 Vector components 重载 def

正确重载运算符

一元运算符

- (__neg__)
+ (__pos__) 最好返回 self 的副本
~ (__invert__) 对整数位按位取反 (~x == -(x+1))

print(~2)
-3

中辍运算符

+

from array import array
from itertools import zip_longest

class Vector:
    typecode = 'd'

    def __init__(self, components) -> None:
        self._componeents = array(self.typecode, components)

    def __iter__(self):
        return iter(self._componeents)

    def __neg__(self):
        return Vector(-x for x in self)

    def __pos__(self):
        return Vector(self)
    
    def __add__(self, other):
        pairs = zip_longest(self, other, fillvalue=0.0)
        return Vector(a + b for a, b in pairs)
    
    def __radd__(self, other):
        return self + other  # 直接委托给 __add__

Counter

collections.Count 计数器

from collections import Counter
ct = Counter('asfsdgasdasfasdgsd')

print(1, ct)
ct['s'] = -2
ct['g'] = 0
print(2, ct)
print(3, +ct)  # 会剔除无意义的 0 和负值
1 Counter({'s': 6, 'a': 4, 'd': 4, 'f': 2, 'g': 2})
2 Counter({'a': 4, 'd': 4, 'f': 2, 'g': 0, 's': -2})
3 Counter({'a': 4, 'd': 4, 'f': 2})
def __add__(self, other):
    try:
        pairs = zip_longest(self, other, fillvalue=0.0)
        return Vector(a + b for a, b in pairs)
    except TypeError:
        return NotImplemented
    
def __radd__(self, other):
    return self + other

-

from array import array
from itertools import zip_longest
import reprlib, numbers

class Vector:
    typecode = 'd'

    def __init__(self, components) -> None:
        self._componeents = array(self.typecode, components)

    def __repr__(self):
        components = reprlib.repr(self._componeents)  # array('d', [1, 2, 3, 4, ...])
        components = components[components.find('['):-1]  # [1, 2, 3, 4, ...]
        return 'Vector({})'.format(components)  # Vector([1, 2, 3, 4])

    def __iter__(self):
        return iter(self._componeents)

    def __mul__(self, scalar):
        if isinstance(scalar, numbers.Real):
            return Vector(n * scalar for n in self)
        else:
            return NotImplemented
    
    def __rmul__(self, scalar):
        return self * scalar
v1 = Vector([1, 2, 3])
print(1, repr(v1 * 10))
print(2, repr(20 * v1))

1 Vector([10.0, 20.0, 30.0])
2 Vector([20.0, 40.0, 60.0])
运算符 正向方法 逆向方法 就地方法 说明
+ __add__ __radd__ __iadd__ 加法或拼接
- __sub__ __rsub__ __isub__ 减法
* __mul__ __rmul__ __imul__ 乘法或重复复制
/ __truediv__ __rtruediv__ __itruediv__ 除法

更多的

运算符 方法名字
// floordiv
% mod
divmod() divmod
**, pow() pow
@ matmul
& and
` `
^ xor
<< lshift
>> rshift

pow(a, b, modulo) <==> a ** b % modulo

@ 是 点积,可在 numpy 中使用,a @ b <==> dot(a, b)

from array import array
from itertools import zip_longest
import reprlib, numbers

class Vector:
    typecode = 'd'

    def __init__(self, components) -> None:
        self._componeents = array(self.typecode, components)

    def __repr__(self):
        components = reprlib.repr(self._componeents)  # array('d', [1, 2, 3, 4, ...])
        components = components[components.find('['):-1]  # [1, 2, 3, 4, ...]
        return 'Vector({})'.format(components)  # Vector([1, 2, 3, 4])

    def __iter__(self):
        return iter(self._componeents)

    def __matmul__(self, other):
        try:
            return sum(a * b for a, b in zip(self, other))
        except TypeError:
            return NotImplemented

    def __rmatmul__(self, other):
        return self @ other

比较运算符

中辍运算符 正向方法调用 后备机制
a == b a.__eq__(b) 返回 id(a) == id(b)
a != b a.__ne__(b) 返回 not (a == b)
a > b a.__gt__(b) 抛出 TypeError
a < b a.__lt__(b) 抛出 TypeError
a >= b a.__ge__(b) 抛出 TypeError
a <= b a.__le__(b) 抛出 TypeError

反向方法调用 b.__xx__(a)

from array import array
from itertools import zip_longest
import reprlib, numbers

class Vector:
    typecode = 'd'

    def __init__(self, components) -> None:
        self._componeents = array(self.typecode, components)

    def __repr__(self):
        components = reprlib.repr(self._componeents)  # array('d', [1, 2, 3, 4, ...])
        components = components[components.find('['):-1]  # [1, 2, 3, 4, ...]
        return 'Vector({})'.format(components)  # Vector([1, 2, 3, 4])

    def __iter__(self):
        return iter(self._componeents)

    def __eq__(self, other):
        if isinstance(other, Vector):
            return (len(self) == len(other) and all(a == b for a, b in zip(self, other)))
        else:
            return NotImplemented

注意:

  • == 会调用 a.__eq__(b) 进行判断

  • a.__eq__(b) 抛出 NotImplemented 异常时,

  • 会调用反向方法 b.__eq__(a) 进行判断,

  • 如果再次得到 NotImplemented, 则返回 False

  • 否则返回 True

在两个自定义 class 时判断是否相等时, 可能第一个 class 抛出 NotImplemented, 而第二个 class 通过, 同样返回 True

!= 类似于 not ==

增量赋值运算符

后面忘保存了。。。

标签:__,return,Python,self,运算符,Vector,components,重载,def
From: https://www.cnblogs.com/Zinc233/p/FluentPython_S13.html

相关文章

  • 回文链表-python
    问题:给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。思考:对称结构要想到stack方案一:双指针法将节点值赋值到数组......
  • Python内容写入文件
       Python允许你将内容写入文件,方式与使用print()函数将字符串‘写’到屏幕上类似,但是,如果打开文件时用读模式,就不能写入,你需要以纯文本模式或添加纯文本模式打开该文......
  • Python 跳动的小球
    一、实验内容:跳动的小球游戏介绍二、实验对象:《零基础学Python》第13章Pygame游戏编程实例01用以下代码创建一个游戏弹窗:导入pygame模块并且用init()方法初始化,设置窗......
  • n202_python数据类型和数据结构
    3.数据类型和数据结构python的数据类型大致可以分为两种:python自带的内置数据类型和第三方扩展包中的数据类型。其中,python自带的内置数据类型可以分为两种:可变数据类......
  • Python爬取中国最好大学排行榜报错TypeError: unsupported format string passed to N
    ​本文使用的是如下网址:http://gaokao.xdf.cn/201911/10991728.html1问题分析与解决报错为类型错误,显示我们传递了不支持的格式字符串1.1strip()我们查看网页源码,......
  • python常用第三方库
    python常用第三方库官网主页查询、下载和发布Python包或库官网地址参考来源网络爬虫requests:https://pypi.org/project/requests/简洁且简单的处理HTTP请求的......
  • [oeasy]python0024_ 输出时间_time_模块_module_函数_function
    输出时间回忆上次内容​print​​函数有个默认的​​end参数​​​end参数​​的值可以是任意字符串​​end参数​​的值会输出到结尾位置​​end参数​​的默认值是......
  • Python调用接口鲁棒化处理防止阻塞
    如果是同其他团队或者系统协作开发,无法保证对方的接口不出问题,所以要考虑一种鲁棒的方法,保证自己的程序不管什么情况下都可以有合适的值返回。1.如果调用对方接口网络不同......
  • [oeasy]python0024_ 输出时间_time_模块_module_函数_function
    ​ 输出时间回忆上次内容​print​​函数有个默认的​​end参数​​​end参数​​的值可以是任意字符串​​end参数​​的值会输出到结尾位置​​end参数......
  • python实现抽奖程序
    基本思路:从LOL英雄联盟中取4个英雄作为抽奖对象,用Flask框架搭建模拟抽奖程序。一、Flask框架的简单应用二、random随机模块的简单应用,生成随机整数三、python完整实例from......