本节的内容是续着上上一节的内容来讲的,面向对象在Python里面是非常重要的一个概念。第十五课讲了一些关于面向对象的饿知识,但是还是不够的。这一章节我们再来补充些。一些很好用的方法和特性。一起来看看吧。
super函数是干什么的?有什么用呢?
super是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序、重复调用等种种问题。具体的我们来看看下面这个例子。
__metaclass__=type
class Bird():
def __init__(self):
self.hungry=True
def eat(self):
if self.hungry:
print 'Aaaaah...'
self.hungry=False
else:
print 'No thanks..'
class SongBird(Bird):
def __init__(self):
super(SongBird, self).__init__() #这样的调用方式要求父类必须是新式类,继承自object。假如你不想用这样的调用方式,那么久要显示调用父类方法:Bird.__init__(self)
self.sound='Squawk!'
def sing(self):
print self.sound
sb=SongBird()
sb.sing()
sb.eat()
sb.eat()
下面是它的运行结果:
/usr/local/bin/python2.7 /Users/yangjiayuan/PycharmProjects/day/day15/function_of_super.py
Squawk!
Aaaaah...
No thanks..
Process finished with exit code 0
关于super函数的内部工作原理在这不做过多介绍,大家可以自行百度。但是必须知道的一点就是:在大多数情况下,使用新式类和super函数是比调用超类的未绑定的构造方法更好的选择。
在前面,我们介绍过一些关于成员访问的知识。尽管__init__方法是到目前为止提到的最重要的特殊方法,但是还有一些其他方法提供的作用也很重要。下面列出的就值得关注。
序列和映射是对象的集合。为了实现它们的基本行为,如果对象是不可变的,那么久需要两个魔法方法。如果对象是可变的,那么需要的规则就要使用四个。
__len__(self)方法 | 这个方法返回集合中所含项目的数量。对于序列来说,这就是元素的个数。对于映射来说,则是键-值对的数量。若返回0则为空。(空列表、空元组、空字符串、空字典等等) |
__getitem__(self,key)方法 | 这个方法返回与所给键对应的值。序列里面,键应该是0~n-1的整数,n是序列的长度。而对于映射来说,可以使用任意类型的键。 |
__setitem__(self,key,value)方法 | 这个方法按一定的方式存储和key相关的value,该值以后可以通过__getitem__来获取。只能为可以修改的对象使用这个方法。 |
__delitem__(self,key) | 这个方法在对一部分对象使用del语句的时候被调用,同时必须删除和键相关测键。也是可以用来修改对象定义的。并不是删除全部的对象,而是移除一些需要移除的元素。 |
我们可以在需要的时候采用这些方法,另外这些方法还需要一定的附加条件:
来看看使用上面方法的例子:
def checkIndex(key):
if not isinstance(key,(int, long)) :raise TypeError
if key<0:raise IndexError
class AirthmeticSequence:
def __init__(self,start=0,step=1):
self.start=start
self.step=step
self.changed={}
def __getitem__(self, key):
checkIndex(key)
try:
return self.changed[key]
except KeyError:
return self.start + key*self.step
def __setitem__(self, key, value):
checkIndex(key)
self.changed[key]=value
s=AirthmeticSequence(1,2)
s[4]=2
print s[4]
print s[5]
需要解释的是一些函数:isinstance()函数用来判断一个对象是否是一个已知的类型,类似于type()。type()不会认为 子类是一种父类类型,不考虑类的继承关系。而isinstance()会认为子类是一种父类类型,考虑继承关系。对应上面的列表,自己实现一下上面的程序,看看最后的结果。
前面的方法是很好用,但是实现起来很麻烦。你需要注意很多细节方面的东西才能很好的使用它们。这时候你可能会想到,如果这样的方法能继承下来多好,就不用这么麻烦了,这样的想法确实在Python里面是可行的。标准库有三个关于序列和映射规则:UserList、UserString、UserDict可以立即使用的实现。来看看:
class CounterList(list):
def __init__(self,*args):
super(CounterList,self).__init__(*args)
self.counter=0
def __getitem__(self, index):
self.counter+=1
return super(CounterList,self).__getitem__(index)
c1=CounterList(range(10))
print c1
c1.reverse()
print c1
del c1[3:6]
print c1
print c1.counter
print c1[4]+c1[2]
/usr/local/bin/python2.7 /Users/yangjiayuan/PycharmProjects/day/day15/funciton_of_classlist.py
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
[9, 8, 7, 3, 2, 1, 0]
0
9
2
Process finished with exit code 0
程序现实的饿结果如上所示,就如你看到的一样,CounterList在很多地方和列表的作用一样,但是它有一个counter特性。每次列表元素被访问的时候它都会自增,当然初始值为0。当c1[4]和c1[2]被访问后,很明显的是c1.counter的值从0变到2。
迭代器我们在前面的知识里面也提到过,迭代器最基础的就是一个__iter__方法,这个方法是迭代器规则的基础。
迭代器意味着我们可以重复做一些事情很多次,就像在循环处理的那里一样。__iter__方法会返回一个迭代器,所谓的迭代器就是具有next的方法,方法调用的时候不需要任何参数。在调用next方法的时候,迭代器会返回它的下一个值。如果next方法被调用,但是迭代器没有值可以返回,此时就会引发一个StopIteration异常。来看一个例子:
class Fibs:
def __init__(self):
self.a=0
self.b=1
def next(self):
self.a,self.b=self.b,self.a+self.b
return self.a
def __iter__(self):
return self
fibs=Fibs()
for f in fibs:
if f>1000:
print f
break
/usr/local/bin/python2.7 /Users/yangjiayuan/PycharmProjects/day/day15/use_of_iteration.py
1597
Process finished with exit code 0
上述例子是实现斐波那契数列的另外一种方法,也就是利用迭代器。这个方法本身返回迭代器本身。很常见的是,__iter__和for循环在一起使用,会放到其他的会在for循环中使用的对象中。这样一来,程序就能返回所需的迭代器。就像上面的一样,我们试着查找在斐波那契数列中比1000大的数里面最小的数,如果找到这个数就终止循环,否则程序循环一直进行下去。除了这样的操作以外,我们还可以从迭代器获得序列--利用list构造方法显示地将迭代器转换为列表。
class TestIteration:
value=0
def next(self):
self.value+=1
if self.value>10:
raise StopIteration
return self.value
def __iter__(self):
return self
ti=TestIteration()
print list(ti)
/usr/local/bin/python2.7 /Users/yangjiayuan/PycharmProjects/day/day15/use_of_iteration.py
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Process finished with exit code 0
从运行结果可以看出,我们确实将迭代器通过list方法转换为了序列并打印了出来。
好咯,这一章节的内容就先介绍到这里啦,多练习最好。下一章节将会介绍一个新的概念--生成器和一个小项目的实现。