欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python-工厂函数

程序员文章站 2022-05-23 19:34:25
...

在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没有给我们提供需要的底层功能(比如字符串减法等)

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

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