Python 妙用运算符重载——玩出“点”花样来

右加 +

右幂 **

右整除 //

总结

实际运用


本篇的主角正是“点”,今天要用运算符重载来,把它玩出“点”花样来!那什么是运算符重载呢?

运算符重载

运算符重载是面向对象编程中的一个概念,它允许程序员为自定义类型(如类或结构体)定义特定的运算符行为,使得这些类的实例可以使用语言中预定义的运算符。在Python等编程语言中,运算符重载是一种强大的特性,它使得我们可以用更加自然和直观的方式处理自定义类型。在实际编程中,我们应该根据需要合理使用这一特性,以提高代码的质量和效率。

主角点类

class Point 这个类很简单,就两个属性:横坐标x和纵坐标y。

class Point:
    def __init__(self, x=0, y=0):
        self.x, self.y = x, y
    def __repr__(self):
        return f'Point({self.x}, {self.y})'
    def __str__(self):
        return f'({self.x}, {self.y})'

测试:

a = Point()
a
Point(0, 0)
str(a)
‘(0, 0)’
b = Point(2, 5)
b
Point(2, 5)

对于只需要整数坐标的类,比如二维数组的行列坐标,本文主要讨论整数坐标值的坐标,可以在类初始化函数里加上类型判断:

class Point:
    def __init__(self, x=0, y=0):
        self.x, self.y = x, y
        assert(isinstance(x, str) and isinstance(y, str))
    def __repr__(self):
        return f'Point({self.x}, {self.y})'
    def __str__(self):
        return f'({self.x}, {self.y})'

测试:

p = Point(2, 5)
p
Point(2, 5)
q = Point(2.1, 5.5)
Traceback (most recent call last):
  File “<pyshell#25>”, line 1, in
    q = Point(2.1, 5.5)
  File “<pyshell#22>”, line 4, in __init__
    assert(isinstance(x, int) and isinstance(y, int))
AssertionError

魔法方法

也称为特殊方法或双下划线方法,是python语言中的一种特殊方法,用于在类中实现一些特殊的功能。这些方法的名称始终以双下划线开头和结尾,比如上面点类定义时用到 __init__,__repr__,__str__。重载运算符时,我们就是靠魔法方法来重新定义运算符的,例如 __add__,__sub__,__mul__,__truediv__ 分别对应加减乘除四则运算。

在重载运算符前,再来学习几个其他类型的魔法方法:

__getitem__

__getitem__ 方法用于获取下标对应的值。

__setitem__

__setitem__ 方法用于设置下标对应的值。

定义完后,点类可以用下标0,1或者-2,-1来取值,和元组、列表等一样:obj[0], obj[1]。

class Point:
    def __init__(self, x=0, y=0):
        self.x, self.y = x, y
    def __repr__(self):
        return f'Point({self.x}, {self.y})'
    def __getitem__(self, index):
        if index in range(-2,2):
            return self.y if index in (1,-1) else self.x
        raise IndexError("Index out of range")
    def __setitem__(self, index, value):
        if index in (0, -2):
            self.x = value
        elif index in (1, -1):
            self.y = value
        else:
            raise IndexError("Index out of range.")

测试:

a = Point(1,2)
a[0], a[1]
(1, 2)
a[-1], a[-2]
(2, 1)
a[0] = 5
a
Point(5, 2)
a[1] = 3
a
Point(5, 3)
[i for i in a]
[5, 3]
x, y = a
x
5
y
3
b = iter(a)
next(b)
5
next(b)
3
next(b)
Traceback (most recent call last):
  File “<pyshell#67>”, line 1, in
    next(b)
StopIteration

__iter__
__next__

共同定义一个对象的迭代行为,迭代器必须实现__iter__()方法,该方法返回迭代器自身,或者返回一个新的迭代器对象。__next__()方法返回迭代器的下一个元素。

class Point:
    def __init__(self, x=0, y=0):
        self.x, self.y = x, y
        self.index = 0
    def __repr__(self):
        return f'Point({self.x}, {self.y})'
    def __iter__(self):
        self.index = 0
        return self
    def __next__(self):
        if self.index < 2:
            result = self.y if self.index else self.x
            self.index += 1
            return result
        else:
            raise StopIteration

测试:

a = Point(5, 3)
x, y = a
x, y
(5, 3)
next(a)
Traceback (most recent call last):
  File “<pyshell#115>”, line 1, in
    next(a)
  File “<pyshell#111>”, line 16, in __next__
    raise StopIteration
StopIteration
a = Point(5, 3)
next(a)
5
next(a)
3
a
Point(5, 3)
a.x
5
next(a)
Traceback (most recent call last):
  File “<pyshell#121>”, line 1, in
    next(a)
  File “<pyshell#111>”, line 16, in __next__
    raise StopIteration
StopIteration
a[0]
Traceback (most recent call last):
  File “<pyshell#122>”, line 1, in
    a[0]
TypeError: ‘Point’ object is not subscriptable

对于点类说,可迭代魔法方法完全可弃用;因为使用__getitem__方法和iter()函数已有此功能。

__len__

求长度的方法,原义就是计算可迭代对象元素的个数;点类的长度就是2。

    def __len__(self):
        return 2
__neg__

求相反数的方法,也就是单目的**“ - ”**符号;重载为横纵坐标都取相反数。

    def __neg__(self):
        return Point(-self.x, -self.y)
__pos__

这是单目的**“ + ”**符号,一般无需重新定义;但是我们还是把它重载成穿过点的横纵两条直线上所有的整数点坐标&

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值