python-工厂函数

在python2.2之前类与类型分开

:封装(属性+方法)
类型:整型、浮点型、字符型、字符串型

但之后作者对这俩统一了
将int()、str()、list()这些BIF转化成了工厂函数。

int()与类d的class是一样的,可以把工厂函数看成类,返回实例对象

type(int)
<class 'type'>
class d:
...     pass
... 
type(d)
<class 'type'>

将类int()进行实例化

a = int('123')
b = int('456')
a+b
579

以前上面的语句是将字符串类型改为整型
现在则是将类int()实例化为a,而“123‘’则是传入的参数

语句:a+b,实际上是对象之间的操作

python专门使用魔法方法定义了对象之间的操作

例如:当检测到对象之间用+号操作时,自动调用int()类中的__add__方法(魔法方法,在需要的时候自动被调用,就像__init__)

下面创建新的类来继承int()的所有方法,然后通过改写__add__方法来让+号不执行相加操作,反而执行相减操作

class re_int(int):

    def __add__(self, other):  # 检测到对象间“+”号,自动执行该方法
        return int.__sub__(self, other)  # 返回值为:int()类中的相减操作

    def __sub__(self, other):  # 检测到对象间“-”号,自动执行该方法
        return int.__add__(self, other)  # 返回值为:int()类中的相加操作

a = re_int('5')
b = re_int('3')
print(a + b)
2  # 运行结果

如此,我们在类re_int()中交换了符号“+”与符号“-”的作用,使由类产生的实例化对象a与b在执行符号:“+”与“-”的操作时并不像通常认知的那样。

我们仿佛深入到了更加底层的代码,上帝之手像你召唤唤唤唤唤!!!

下面让我们来康康父类int()中的魔法方法是如何实现的:

(dir(类名):查看类中所有方法名和属性名)
(help(类名.方法名):查看类中方法)

help(int.__add__)
Help on wrapper_descriptor:
__add__(self, value, /)
    Return self+value.
help(int.__sub__)
Help on wrapper_descriptor:
__sub__(self, value, /)
    Return self-value.

上面我们看到了int()类中add方法的实现过程

如果将我们的re_int类不继承int而是自己定义add方法能实现实例对象的加法运算吗?

class re_int(int):

    def __add__(self, other,/):  # 检测到对象间“+”号,自动执行该方法
        return self+other # 返回值为:int()类中的相减操作

    def __sub__(self, other,/):  # 检测到对象间“-”号,自动执行该方法
        return self-other # 返回值为:int()类中的相加操作
a = re_int('5')
b = re_int('3')
print(a+b)

运行结果发现超出做大递归数

Traceback (most recent call last):
  File "D:/FishC/作业/41_48_魔法方法/11.py", line 17, in <module>
    print(a+b)
  File "D:/FishC/作业/41_48_魔法方法/11.py", line 8, in __add__
    return self+other # 返回值为:int()类中的相减操作
  File "D:/FishC/作业/41_48_魔法方法/11.py", line 8, in __add__
    return self+other # 返回值为:int()类中的相减操作
  File "D:/FishC/作业/41_48_魔法方法/11.py", line 8, in __add__
    return self+other # 返回值为:int()类中的相减操作
  [Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded

要想正确运行可以在返回前面加上int(),这样返回的是整型的相加

class re_int(int):

    def __add__(self, other,/):  # 检测到对象间“+”号,自动执行该方法
        return int(self)+int(other) # 返回值为:int()类中的相减操作

    def __sub__(self, other,/):  # 检测到对象间“-”号,自动执行该方法
        return int(self)-int(other) # 返回值为:int()类中的相加操作
a = re_int('5')
b = re_int('3')
print(a+b)

例子1:

两个字符串相加会自动拼接字符串,但遗憾的是两个字符串相减却抛出异常。
因此,现在我们要求定义一个 Nstr 类,支持字符串的相减操作:
A – B,从 A 中去除所有 B 的子字符串

class Nstr(str):

    def __sub__(self, other):
        for each in other:
            if each in self:
                self = self.replace(each, '')
        return str(self)

运行结果:
Nstr类继承str类的所有属性和方法:

检测到减号自动调用__sub__魔法方法
(虽然str类中没有__sub__方法,但是子类Nstr产生的实例遇到“-”号仍然会自动运行__sub__方法)

self是a,other是b
(a与b都是同一个类产生的对象,所以能调用共同的类方法进行操作)

>>> a = Nstr('I love FishC.com!iiiiiiii')
>>> b = Nstr('i')
>>> print(a - b)

I love FshC.com!

例子2:
#定义一个类 Nstr
#当该类的实例对象间发生的加、减、乘、除运算时
#将该对象的所有字符串的 ASCII 码之和进行计算
#查看ASCII: ord(字符)


class Nstr(str):

    def __add__(self, other):	# 遇到符号:+   自动运行魔法方法__add__(NB)
        s1 = 0
        s2 = 0
        for each in self:
            s1 += int(ord(each))
        for each in other:
            s2 += int(ord(each))
        return s1 + s2

    def __sub__(self, other):
        s1 = 0
        s2 = 0
        for each in self:
            s1 += int(ord(each))
        for each in other:
            s2 += int(ord(each))
        return s1 - s2

    def __mul__(self, other):
        s1 = 0
        s2 = 0
        for each in self:
            s1 += int(ord(each))
        for each in other:
            s2 += int(ord(each))
        return s1 * s2

    def __truediv__(self, other):
        s1 = 0
        s2 = 0
        for each in self:
            s1 += int(ord(each))
        for each in other:
            s2 += int(ord(each))
        return s1 / s2
        

运行结果:


>>> a = Nstr('FishC')
>>> b = Nstr('love')
print(a+b,a-b,a*b,a/b)

899 23 201918 1.052511415525114

通过以上两个算例我们可以看出:

虽然python没有给我们提供需要的底层功能(比如字符串减法等)

但有了工厂函数我们可以根据需要自己定义需要的功能

这使我们的编程更加的灵活

猜你喜欢

转载自blog.csdn.net/weixin_40960364/article/details/105832704