前提
重新提起一个函数,工厂函数。其实在Python2.2之前类和类型是分开的,类就是一个属性和方法的一个封装,类型就是像(int,float....)。但是2.2之后,作者将两个东西做了统一,将int float等内置函数转化为工厂函数。
举个例子:
>>> type(len)
<class 'builtin_function_or_method'>
>>> type(dir)
<class 'builtin_function_or_method'>
>>> type(int)
<class 'type'>
>>> type(list)
<class 'type'>
>>> class C:
pass
>>> type(C)
<class 'type'>
>>> int('123')
123
>>> a=int('123')
>>> a
123
>>> b=int('456')
>>> a+b
579
所以工厂函数就是类对象。。。
知识点 :
1.__add__(self,other)魔法方法
>>> class New_int(int):#调用魔法方法__add__,__sub__
def __add__(self,other):
return int.__sub__(self,other)
def __sub__(self,other):
return int.__add__(self,other)
>>> a=New_int(3)
>>> b=New_int(5)
>>> a+b
-2
>>> a-b
8
>>> class Try_int(int):
def __add__(self,other):
return self+other#以加法为例,a=self,b=other,然后又返回a+b所以会一直递归
def __sub__(self,other):
return self-other
>>> a=Try_int(5)
>>> b=Try_int(6)
>>> a-b
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
a-b
File "<pyshell#28>", line 5, in __sub__
return self-other
File "<pyshell#28>", line 5, in __sub__
return self-other
File "<pyshell#28>", line 5, in __sub__
return self-other
[Previous line repeated 990 more times]
RecursionError: maximum recursion depth exceeded
>>> a+b
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
a+b
File "<pyshell#28>", line 3, in __add__
return self+other
File "<pyshell#28>", line 3, in __add__
return self+other
File "<pyshell#28>", line 3, in __add__
return self+other
[Previous line repeated 990 more times]
RecursionError: maximum recursion depth exceeded
#更改,改正
>>> class Try_int(int):
def __add__(self,other):
return int(self)+int(other)
def __sub__(self,other):
return int(self)-int(other)
>>> a=Try_int(3)
>>> b=Try_int(4)
>>> a+b
7
其他的魔法方法在这里可以查找到
测试题
0.自Python2.2以后,对类和类型进行了统一,做法就是将int(),float(),str(),list(),tuple()这些BIF转换为工厂函数,请问所谓的工厂函数,其实是什么原理?
答:工厂函数,其实就是一个类对象,当调用他们的时候,事实上就是创建一个相应的实例对象。
1.当实例对象进行加法操作时,会自动调用什么魔法方法?
答:对象a和b相加(a+b),Python会自动根据对象a的__add__魔法方法进行加法操作。
2.下面代码有问题吗?(运行起来似乎没出错的说。。。)
>>> class Foo:
def foo(self):
self.foo = "T love Fish.com!"
return self.foo
>>>
>>> foo = Foo()
>>> foo.foo()
'T love Fish.com!'
答:这绝对是一个温柔的陷阱,这种BUG比较难以排除,所以一定要注意:类的属性名和方法名绝对不能相同!如果代码这么写,就会有一个难以排查的BUG出现?
>>> class Foo:
def __init__(self):
self.foo = "I love fish..c"
def foo(self):
return self.foo
>>> foo =Foo()
>>> foo.foo()
Traceback (most recent call last):
File "<pyshell#49>", line 1, in <module>
foo.foo()
TypeError: 'str' object is not callable
3.写出下列算术运算符对应的魔法方法?
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)
>>> a
9
>>> b
[1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]
>>> c
'loveFishCloveFishCloveFishC'
答:说明Python支持鸭子类型风格
动动手
0.我们都知道在Python中,两个字符串相加会自动拼接字符串,但遗憾的是两个字符串相减缺抛出异常,因此,现在我们要求定一个Nstr类,支持字符串的相减操作:A-B,从A中去除所有B的子字符串。
>>> class Nstr(str):
def __sub__(self,other):
return self.replace(other,'')
>>> a=Nstr('I love Ficshc!!!!IIIIIII')
>>> b=Nstr('I')
>>> a-b
' love Ficshc!!!!'
1.移位操作符是应用于二进制操作数的,现在需要你定义一个新的类Nstr,也支持移位操作符运算。
>>> class Nstr(str):
def __lshift__(self,other):
return self[other:]+self[:other]
def __rshift__(self,other):
return self[:-other]+self[-other:]
>>> a=Nstr('gogogogogogogobutbecause')
>>> a<<3
'ogogogogogobutbecausegog'
>>> a>>3
'gogogogogogogobutbecause'
2.定义一个类Nstr,当该类的实例对象间发生加,减,乘,除运算时,该对象的所有字符串的ASCLL码之和进行运算?
>>> 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
>>>
>>> a=Nstr('Fishc')
>>> b=Nstr('love')
>>> a+b
931
>>> a-b
55
>>> a*b
215934
>>> a/b
1.1255707762557077