Python入门基础第十七课--方法、属性、迭代器等

1.前言

    本节的内容是续着上上一节的内容来讲的,面向对象在Python里面是非常重要的一个概念。第十五课讲了一些关于面向对象的饿知识,但是还是不够的。这一章节我们再来补充些。一些很好用的方法和特性。一起来看看吧。

2.super函数

    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函数是比调用超类的未绑定的构造方法更好的选择。

3.成员访问

    在前面,我们介绍过一些关于成员访问的知识。尽管__init__方法是到目前为止提到的最重要的特殊方法,但是还有一些其他方法提供的作用也很重要。下面列出的就值得关注。

3.1基本序列和映射规则

    序列和映射是对象的集合。为了实现它们的基本行为,如果对象是不可变的,那么久需要两个魔法方法。如果对象是可变的,那么需要的规则就要使用四个。

__len__(self)方法 这个方法返回集合中所含项目的数量。对于序列来说,这就是元素的个数。对于映射来说,则是键-值对的数量。若返回0则为空。(空列表、空元组、空字符串、空字典等等)
__getitem__(self,key)方法 这个方法返回与所给键对应的值。序列里面,键应该是0~n-1的整数,n是序列的长度。而对于映射来说,可以使用任意类型的键。
__setitem__(self,key,value)方法 这个方法按一定的方式存储和key相关的value,该值以后可以通过__getitem__来获取。只能为可以修改的对象使用这个方法。
__delitem__(self,key) 这个方法在对一部分对象使用del语句的时候被调用,同时必须删除和键相关测键。也是可以用来修改对象定义的。并不是删除全部的对象,而是移除一些需要移除的元素。

    我们可以在需要的时候采用这些方法,另外这些方法还需要一定的附加条件:

  • 序列中,如果键是负整数,那么要从末尾开始计数。
  • 如果键不是合适的类型就会引发一个类型错误,TypeError异常。
  • 如果序列的索引是正确的类型,但是超出了范围,则会引发一个IndexError异常。

    来看看使用上面方法的例子:    

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()会认为子类是一种父类类型,考虑继承关系。对应上面的列表,自己实现一下上面的程序,看看最后的结果。

3.2子类化列表、字典和字符串

    前面的方法是很好用,但是实现起来很麻烦。你需要注意很多细节方面的东西才能很好的使用它们。这时候你可能会想到,如果这样的方法能继承下来多好,就不用这么麻烦了,这样的想法确实在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。

4.迭代器

    迭代器我们在前面的知识里面也提到过,迭代器最基础的就是一个__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方法转换为了序列并打印了出来。

    好咯,这一章节的内容就先介绍到这里啦,多练习最好。下一章节将会介绍一个新的概念--生成器和一个小项目的实现。




你可能感兴趣的:(Python,Python学习之路)