魔法方法:算术运算+习题复习

##算术运算
            (在Python2.2之前,类和类型是分开的,是不同的东西,类就是一个属性和方法的一个封装,而类型就是像我们的整型啊、浮点型啊,字符串啊之类的,但是在Python2.2之后,作者试图对这两个东西进行统一,做法就是将 int()、float()、str()、list()、tuple() 这些 BIF 转换为工厂函数,那什么是工厂函数呢?)
在这里插入图片描述

            (当换成int、list、以及自己定义的类)
魔法方法:算术运算+习题复习_第1张图片
            (返回的是class“type”,当一个类定义完了之后他叫做类对象,也就说,所谓的工厂函数事实上就上类对象)
            (Python的魔法方法还提供了让你自定义对象的数值处理,通过对我们这些魔法方法进行重写,你可以自定义任何对象间的算术运算。)

__add__(self, other)

定义加法的行为:+

__sub__(self, other)

定义减法的行为:-

__mul__(self, other)

定义乘法的行为:*

__truediv__(self, other)

定义真除法的行为:/

__floordiv__(self, other)

定义整数除法的行为://

__mod__(self, other)

定义取模算法的行为:%

__divmod__(self, other)

定义当被 divmod() 调用时的行为,divmod(a, b)返回一个元组:(a//b, a%b)

__pow__(self, other[, modulo])

定义当被 power() 调用或 ** 运算时的行为

__lshift__(self, other)

定义按位左移位的行为:<<

__rshift__(self, other)

定义按位右移位的行为:>>

__and__(self, other)

定义按位与操作的行为:&

__xor__(self, other)

定义按位异或操作的行为:^

__or__(self, other)

定义按位或操作的行为:|

魔法方法:算术运算+习题复习_第2张图片
            (这里做了个恶作剧,当a+b被调用时,看到是加法,就会去自动调用add的魔法方法,但我们 返回的不是两者相加,而是两者相减)
魔法方法:算术运算+习题复习_第3张图片
            (这样会发生无限递归,直到达到python设点的递归深度,当执行a+b,首先是发现加法,执行魔法方法add,b就是other,但是return的时候又是return a+b,self就是和啊绑定的,所以又是发现加法,然后就会一直递归)

##温故知新之习题
            0. 自 Python2.2 以后,对类和类型进行了统一,做法就是将 int()、float()、str()、list()、tuple() 这些 BIF 转换为工厂函数。请问所谓的工厂函数,其实是什么原理?
           答:工厂函数,其实就是一个类对象。当你调用他们的时候,事实上就是创建一个相应的实例对象。

# a 和 b 是工厂函数(类对象) int 的实例对象
>>> a = int('123')
>>> b = int('345')
>>> a + b
468

            1. 当实例对象进行加法操作时,会自动调用什么魔法方法?
           答:对象 a 和 b 相加时(a + b),Python 会自动根据对象 a 的 __add__ 魔法方法进行加法操作。

            2. 下边代码有问题吗?(运行起来似乎没出错的说^_^)

class Foo:
        def foo(self):
                self.foo = "I love FishC.com!"
                return self.foo
 
>>> foo = Foo()
>>> foo.foo()
'I love FishC.com!'

           答:这绝对是一个温柔的陷阱,这种BUG比较难以排查,所以一定要注意:类的属性名和方法名绝对不能相同!如果代码这么写,就会有一个难以排查的BUG出现了:

class Foo:
        def __init__(self):
                self.foo = "I love FishC.com!"
        def foo(self):
                return self.foo
 
>>> foo = Foo()
>>> foo.foo()
Traceback (most recent call last):
  File "", line 1, in 
    foo.foo()
TypeError: 'str' object is not callable

            3. 写出下列算术运算符对应的魔法方法:
           答:

运算符

对应的魔法方法

+

__add__(self, other)

-

__sub__(self, other)

*

__mul__(self, other)

/

__truediv__(self, other)

//

__floordiv__(self, other)

%

__mod__(self, other)

divmod(a, b)

__divmod__(a, b)

**

__pow__(self, other[, modulo])

<<

__lshift__(self, other)

>>

__rshift__(self, other)

&

__and__(self, other)

^

__xor__(self, other)

|

__or__(self, other)

            4. 以下代码说明 Python 支持什么风格?

def calc(a, b, c):
        return (a + b) * c
 
>>> a = calc(1, 2, 3)
>>> b = calc([1, 2, 3], [4, 5, 6], 2)
>>> c = calc('love', 'FishC', 3)
>>> print(a)
9
>>> print(b)
[1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]
>>> print(c)
loveFishCloveFishCloveFishC

           答:说明 Python 支持鸭子类型(duck typing)风格。
           详见:Python扩展阅读:鸭子类型(duck typing)

##动动手

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

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

           答:只需要重载 __sub__ 魔法方法即可。

class Nstr(str):
    def __sub__(self, other):
        return self.replace(other, '')

           1. 移位操作符是应用于二进制操作数的,现在需要你定义一个新的类 Nstr,也支持移位操作符的运算:

>>> a = Nstr('I love FishC.com!')
>>> a << 3
'ove FishC.com!I l'
>>> a >> 3
'om!I love FishC.c'

           答:只需要重载 __lshift__ 和 rshift 魔法方法即可。

class Nstr(str):
    def __lshift__(self, other):
        return self[other:] + self[:other]
 
    def __rshift__(self, other):
        return self[-other:] + self[:-other]

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

>>> a = Nstr('FishC')
>>> b = Nstr('love')
>>> a + b
899
>>> a - b
23
>>> a * b
201918
>>> a / b
1.052511415525114
>>> a // b
1

           答:

class Nstr:
    def __init__(self, arg=''):
        if isinstance(arg, str):
            self.total = 0
            for each in arg:
                self.total += ord(each)
        else:
            print("参数错误!")
 
    def __add__(self, other):
        return self.total + other.total
 
    def __sub__(self, other):
        return self.total - other.total
 
    def __mul__(self, other):
        return self.total * other.total
 
    def __truediv__(self, other):
        return self.total / other.total
 
    def __floordiv__(self, other):
        return self.total // other.total

           当然,你还可以这样做:

class Nstr(int):
    def __new__(cls, arg=0):
        if isinstance(arg, str):
            total = 0
            for each in arg:
                total += ord(each)
            arg = total
        return int.__new__(cls, arg)

你可能感兴趣的:(Python)