《零基础入门学习Python》第042讲:魔法方法:算术运算

文章介绍了Python2.2之后类和类型的统一,通过工厂函数如int(),list()等创建实例。同时阐述了Python中的魔法方法,如__add__,__sub__等用于自定义对象的算术运算行为。举例展示了如何改写这些方法实现特定的操作,如交换加法和减法的行为。此外,提到了Python中的鸭子类型,并给出了定义新类支持字符串相减和移位操作的示例。
摘要由CSDN通过智能技术生成

0. 请写下这一节课你学习到的内容:格式不限,回忆并复述是加强记忆的好方式!

在Python2.2之前,类和类型是分开的,在Python2.2之后,作者试图对这两个东西进行统一,做法就是将 int()、float()、str()、list()、tuple() 这些 BIF 转换为工厂函数,那什么是工厂函数呢?

我们试图演示一下:

 
  1. >>> type(len)

  2. <class 'builtin_function_or_method'>

len()是一个普通的内置函数,返回类似也告诉了我们这一点,但是

 
  1. >>> type(int)

  2. <class 'type'>

  3. >>> type(list)

  4. <class 'type'>

然后我们发现:

 
  1. >>> class C:

  2. pass

  3. >>> type(C)

  4. <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)

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

例如:

 
  1. >>> class New_int(int):

  2. def __add__(self, other):

  3. return int.__sub__(self, other)

  4. def __sub__(self, other):

  5. return int.__add__(self, other)

  6. >>> a = New_int(3)

  7. >>> b = New_int(5)

  8. >>> a + b

  9. -2

  10. >>> a - b

  11. 8

发现了没,我在这里对原有 int 的加法和减法进行了改写,把加法变为减法,减法变为加法。


测试题

0. 自 Python2.2 以后,对类和类型进行了统一,做法就是将 int()、float()、str()、list()、tuple() 这些 BIF 转换为工厂函数。请问所谓的工厂函数,其实是什么原理?

答:工厂函数,其实就是一个类对象。当你调用他们的时候,事实上就是创建一个相应的实例对象。

 
  1. # a 和 b 是工厂函数(类对象) int 的实例对象

  2. >>> a = int('123')

  3. >>> b = int('345')

  4. >>> a + b

  5. 468

1. 当实例对象进行加法操作时,会自动调用什么魔法方法?

答:对象 a 和 b 相加时(a + b),Python 会自动根据对象 a 的 __add__ 魔法方法进行加法操作。

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

 
  1. class Foo:

  2. def foo(self):

  3. self.foo = "I love FishC.com!"

  4. return self.foo

  5. >>> foo = Foo()

  6. >>> foo.foo()

  7. 'I love FishC.com!'

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

 
  1. class Foo:

  2. def __init__(self):

  3. self.foo = "I love FishC.com!"

  4. def foo(self):

  5. return self.foo

  6. >>> foo = Foo()

  7. >>> foo.foo()

  8. Traceback (most recent call last):

  9. File "<pyshell#21>", line 1, in <module>

  10. foo.foo()

  11. 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 支持什么风格?

 
  1. def calc(a, b, c):

  2. return (a + b) * c

  3. >>> a = calc(1, 2, 3)

  4. >>> b = calc([1, 2, 3], [4, 5, 6], 2)

  5. >>> c = calc('love', 'FishC', 3)

  6. >>> print(a)

  7. 9

  8. >>> print(b)

  9. [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]

  10. >>> print(c)

  11. loveFishCloveFishCloveFishC

答:说明 Python 支持鸭子类型(duck typing)风格。

详见:Python扩展阅读:鸭子类型(duck typing)


动动手

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

示例:

 
  1. >>> a = Nstr('I love FishC.com!iiiiiiii')

  2. >>> b = Nstr('i')

  3. >>> a - b

  4. 'I love FshC.com!'

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

 
  1. class Nstr(str):

  2. def __sub__(self, other):

  3. return self.replace(other, '')

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

 
  1. >>> a = Nstr('I love FishC.com!')

  2. >>> a << 3

  3. 'ove FishC.com!I l'

  4. >>> a >> 3

  5. 'om!I love FishC.c'

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

 
  1. class Nstr(str):

  2. def __lshift__(self, other):

  3. return self[other:] + self[:other]

  4. def __rshift__(self, other):

  5. return self[-other:] + self[:-other]

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

 
  1. >>> a = Nstr('FishC')

  2. >>> b = Nstr('love')

  3. >>> a + b

  4. 899

  5. >>> a - b

  6. 23

  7. >>> a * b

  8. 201918

  9. >>> a / b

  10. 1.052511415525114

  11. >>> a // b

  12. 1

代码清单:

 
  1. class Nstr:

  2. def __init__(self, arg=''):

  3. if isinstance(arg, str):

  4. self.total = 0

  5. for each in arg:

  6. self.total += ord(each)

  7. else:

  8. print("参数错误!")

  9. def __add__(self, other):

  10. return self.total + other.total

  11. def __sub__(self, other):

  12. return self.total - other.total

  13. def __mul__(self, other):

  14. return self.total * other.total

  15. def __truediv__(self, other):

  16. return self.total / other.total

  17. def __floordiv__(self, other):

  18. return self.total // other.total

当然,你还可以这样做:

 
  1. class Nstr(int):

  2. def __new__(cls, arg=0):

  3. if isinstance(arg, str):

  4. total = 0

  5. for each in arg:

  6. total += ord(each)

  7. arg = total

  8. return int.__new__(cls, arg)

另有不明白的,可参阅->Python魔法方法详解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值