python算术运算符重载、迭代器、call魔术方法和单例设计模式

风流意气都作罢 提交于 2020-03-07 03:41:42

1.算术运算符重载

我们知道在python中有字符串的相加、数字常量的相加,那么对于我们自定义的类实例化后的对象是否可以进行相加呢?答案是可以的。这里就要我们对于算术运算符进行重载。下面我们以__add__和__iadd__重载为例,讲解算术运算符的重载。

1.1.__add__

__add__是用来定义加法的魔术方法。

我们来看下面的例子,

class Dog:
    def __init__(self, amount, name):
        self.amount = amount
        self.name = name

    def __add__(self, other):  # 定义两个类相加的结果,other为其他类
        return Dog(self.amount + other.amount, self.name)  # 返回一个新类


d1 = Dog(23, "Tom")
d2 = Dog(21, "Jerry")
res = d1 + d2  # 等价于 d1.__add__(d2) 等价于 __add__(d1, d2)
print(res)
print(res.amount)
print(res.name)
print(type(res))

执行结果如下,

<__main__.Dog object at 0x000002272FB1A408>
44
Tom
<class '__main__.Dog'>

注意,这里我们定义相加是返回一个新类,而不是一个值。为什么要返回一个类呢?

因为一般来说加法是同类型相加,返回一个同类型的结果。

按照本例来说,一个Dog类和另外一个Dog类结果应该返回一个新的Dog类。两个数字相加应该返回另一个数字,而不应该返回一个字符串。

同时注意,我们仅仅定义了该类的加法原则,并没有改变其他的加法原则。

1.2.__iadd__

__iadd__方法用来定义“+=”的原则。

“+=”与“+”有本质的区别,“+”会产生一个新的结果,并不会改变两个加数的属性值。但是“+=”会改变加数本身的属性值。例如,

class Dog:
    def __init__(self, amount, name):
        self.amount = amount
        self.name = name

    def __add__(self, other):  # 定义两个类相加的结果,other为其他类
        return Dog(self.amount + other.amount, self.name)  # 返回一个新类

    def __iadd__(self, other):  # 定义"+="的结果,other为其他类
        self.amount += other.amount  # 改变self.amount的属性值
        return self  # 返回自身


d1 = Dog(23, "Tom")
d2 = Dog(21, "Jerry")
d1 += d2
print(d1.amount)

执行结果如下,

44

2.迭代器

如果想让⼀个类⽤于for-in循环则必须实现__ iter__和__ next__⽅法.。

例如,我们来定义一个输出斐波那契数列的类,

class Fib:
    i = 0

    def __init__(self, n):
        self.n = n
        self.x = 0
        self.y = 1

    def __iter__(self):  # 不可或缺
        return self  # 返回本身

    def __next__(self):  # 定义下一个返回值
        self.__class__.i += 1
        self.x, self.y = self.y, self.x + self.y  # 迭代
        if self.n < self.__class__.i:
            raise StopIteration  # 停止遍历
        return self.x  # 返回值


fib1 = Fib(10)
for i in fib1:
    print(i)

3.__call__

如果⼀个类实现了__call__(slef, *args, **kwargs)⽅法,则该类的对象可以象函数⼀样调⽤。它是实现类装饰器的基础。

4.单例设计模式

设计模式是指对特定问题的⼀种解决⽅案,和平台、语⾔⽆关。

理解设计模式有助于我们更好的理解⾯向对象,让你的代码更加优雅,使你的代码更加容易扩展和复⽤,同时设计模式也是⾯试时候的重点。

设计模式的基本原则有⾼内聚,低耦合(即尽量使用自己定义的函数和类,不要过多的依赖他人的类和函数);单⼀职责(一个类只为实现一个特定的功能);开闭原则(对修改封闭、对扩展开放。在项目开发的过程中,项目成员会互相使用类和函数,如果我们任意的对已有的类进行修改,会出现他人的代码无法使用的情况)。

所谓单例也就是⼀个类只⽣成⼀个对象,⽆论你实例化多少对象,都是同⼀个对象。常见的单例有数据库操作类,⽂件操作类等。单例可以减少资源的占⽤。

下面我们来定义一个单例,

class Singleton:
    __instance = None   #保存实例的引⽤

    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:  #如果实例没有实例化
            cls.__instance = object.__new__(cls, *args, **kwargs)  # 实例化对象,将引⽤存到__instance
        return  cls.__instance #返回对象


s1 = Singleton()
s2 = Singleton()
print(id(s1), id(s2))
if s1 is s2:
    print('单例')

执行结果如下,

2157082821192 2157082821192
单例
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!