15. Python脚本学习笔记十五特殊方法、属性和迭代器

来源:互联网 发布:vue js 折叠面板例子 编辑:程序博客网 时间:2024/06/06 08:43

15. Python脚本学习笔记十五特殊方法、属性和迭代器

本篇名言:“得糊涂是一种境界,心平如境是一种修养,顺其自然是一种超脱,威武不屈是一种品格,富贵不淫是一种情操,常笑就是健康,快乐成就人生。愿你我共勉!”

在Python中,有些名称会在前后加上两个下划线,这种拼写表示名字有特殊含义。所以绝不要在自己的程序中使用这种名字。

 

1.  __init__方法

Python 类中有默认的构造函数__init__我们可以覆盖它来试试。如下:

classFooBar:

    def__init__(self):

        self.somevar=42

f=FooBar()

printf.somevar

我们修改一下如下:

classFooBar:

    def__init__(self,value=42):

        self.somevar=value

f=FooBar("what's this?")

print f.somevar

输出如下:

what'sthis?

 

2.  重写方法

如果一个方法在B类的一个实例中被调用,但在B类中没有找到方法,那么就会在超类A里面找。

如下所示:

classA:

    defhello(self):

        print"hello ,I.m A"

classB(A):

    pass

 

a=A()

b=B()

a.hello()

b.hello()

输出如下:

hello,I.m A

hello,I.m A

B类没有定义自己的方法hello调用的是父类的hello方法。

如果进行重写这个方法,如下:

classA:

    defhello(self):

        print"hello ,I.m A"

classB(A):

    pass

    defhello(self):

        print"Hello,I'm B"

 

a=A()

b=B()

a.hello()

b.hello()

输出如下:

hello,I.m A

Hello,I'm B

 

 

3.  使用Super函数

我看来看下个例子如下:

classBird:

    def__init__(self):

        self.hungry=True

    defeat(self):

        ifself.hungry:

            print'Aaah...'

            self.hungry=False

        else:

                print"No,thansk"

       

classSongBird(Bird):

    def__init__(self):

        self.sound='Squawk!'

    defsing(self):

        printself.sound

 

sb=SongBird()

sb.sing()

sb.eat()

运行如下:

Squawk!

Traceback(most recent call last):

AttributeError:SongBird instance has no attribute 'hungry'

没有hungry属性。

没有得到父类的属性,需要用到Super函数,处理后如下:

from_pyioimport__metaclass__

__metaclass__=type

classBird:

    def__init__(self):

        self.hungry=True

    defeat(self):

        ifself.hungry:

            print'Aaah...'

            self.hungry=False

        else:

                print"No,thansk"

       

classSongBird(Bird):

    def__init__(self):

     #   Bird.__init__(self)

        super(SongBird,self).__init__()

        self.sound='Squawk!'

    defsing(self):

        printself.sound

 

sb=SongBird()

sb.sing()

sb.eat()

 

运行如下:

Squawk!

Aaah...

 

4.  成员访问

在其他语言中对象可能被要求属于某一个类,或者被要求实现某个接口,但是Python中只是简单地要求它遵循几个给定的规则。

                  序列和映射是对象的集合。为了实现他们基本的规则,对于可变的对象需要如下4个方法:

                  输入如下代码:

defcheckIndex(key):

    ifnotisinstance(key,(int,long)):raiseTypeError

    if key<0:raise IndexError

 

classArithmeticSequence:

    def__init__(self,start =0,step=1):

        self.start=start

        self.step=step

        self.changed={}

   

    def__getitem__(self,key):

        checkIndex(key)

       

        try:returnself.changed[key]

        except KeyError:

            returnself.start+key*self.step

    def__setitem__(self,key,value):

        checkIndex(key)

        self.changed[key]=value

 

 

s=ArithmeticSequence(1,2)

s[4]

prints[4]

s[4]=2

prints[4]

print s[5]

输出如下:

9

2

11

最开始的s[4]=start+key*step =1+4*2=9

修改后就直接返回修改后的值。

s[5]=start+key*step=1+5*2=11

当操作del s[4],时候都会报错

AttributeError:ArithmeticSequence instance has no attribute '__delitem__'

 

应为没有实现__del__方法。

当执行s[“four”],

    if not isinstance(key,(int,long)): raiseTypeError

TypeError

s[-42]

    if key<0: raise IndexError

IndexError

 

                  标准库有3个关于序列和映射规则(UserList,UserString和UserDict),可以子类化内建类型。

看如下示例,CounterList 类严重依赖于它的子类化超类(list)的行为。没有重写任何的方法。在__init__中添加了所需的初始化counter特性的行为,并在__getitem__中更新了counter特性。

 

classCounterList(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))

printc1

c1.reverse()

printc1

delc1[3:6]

printc1

printc1.counter

printc1[4]+c1[2]

c1.counter

执行如下:

[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

包含一个counter特性,每次列表元素被访问时,都会自增,在执行c1[4]+c1[2]后,自增两次,变为2.

 

5.  属性

来看个示例:

classRectangle:

    def__init__(self):

        self.width=0

        self.height=0

    defsetSize(self,size):

        self.width,self.height=size

    defgetSize(self):

        returnself.width,self.height

 

r=Rectangle()

r.width=10

r.height=5

printr.getSize()

 

r.setSize((150,100))

print r.width

输出如下:

(10,5)

150

通过访问器定义的特性被称为属性。

                  在Pyhton中有两种创建属性的机制。当前常用的是property函数。

修改成如下:

from_pyioimport__metaclass__

__metaclass__=type

classRectangle:

    def__init__(self):

        self.width=0

        self.height=0

    defsetSize(self,size):

        self.width,self.height=size

    defgetSize(self):

        returnself.width,self.height

    size=property(getSize,setSize)

r=Rectangle()

r.width=10

r.height=5

printr.size

r.size = 150,100

print r.width

输出如下:

(10,5)

150

                  理论上应该使用property函数而不是访问器方法。

                  静态方法和类成员方法分别在创建的时装入Staticmethod类型和Classmethod。类型的对象中。静态方法的定义没有self参数,且能够被类本身直接调用。

如下示例:

classMyClass:

    @staticmethod

    defsmeth():

        print'This is a static method'

    @classmethod

    defcmeth(cls):

        print'This is a class method of', cls

 

MyClass.smeth()

MyClass.cmeth()

输出如下:

Thisis a static method

Thisis a class method of __main__.MyClass

                  不过静态方法和类方法在Python中并不是很重要,因为大部分情况下可以使用函数或者绑定方法替换。

6.  拦截对象的特性访问

为了在访问特性的时候可以执行代码,需要使用如下4种方法。

 

classRectangle:

    def__init__(self):

        self.width=0

        self.height=0

    def__setattr__(self,name,value):

        if name=='size':

            self.width,self.height= value

            print'setattr'

        else:

            self.__dict__[name] = value

    def__getattr__(self,name):

        if name=='size':

            print'getattr'

            returnself.width,self.height           

        else:

            raise AttributeError

 

    defsetSize(self,size):

        self.width,self.height=size

    defgetSize(self):

        returnself.width,self.height

    size=property(getSize,setSize)

 

r=Rectangle()

r.width=10

r.height=5

printr.size

r.size = 150,100

print r.width

 

输出如下:

(10,5)

setattr

150

 

 

7.  迭代器

方法__iter__ 是迭代器规则的基础。__iter__方法返回一个迭代器,所谓迭代器就是具有next方法的对象,这个方法在调用时不需要任何参数。

一个实现了__iter__方法的对象时可迭代的,一个实现了next方法的对象则是迭代器。

我们来实现一个迭代器:

classFibs:

    def__init__(self):

        self.a=0

        self.b=1

    defnext(self):

        self.a,self.b =self.b,self.a+self.b

        returnself.a

    def__iter__(self):

        returnself

 

 

fibs=Fibs()

 

forfin fibs:

    if f>1000:

        print f

        break

输出如下:

1597

 

此外内建函数iter可以从可迭代的对象中获得迭代器,如下:

>>> it=iter([1,2,3])

>>> it.next()

1

>>> it.next()

2

除了在迭代器和可迭代对象上进行迭代外,还能把他们转换为序列。

使用迭代器获得序列,如下代码:

classTestIterator:

    value=0

    defnext(self):

        self.value+=1

        ifself.value>10:raiseStopIteration

        returnself.value

    def__iter__(self):

        returnself

 

ti=TestIterator()

print list(ti)

输出如下:

[1, 2,3, 4, 5, 6, 7, 8, 9, 10]

 

阅读全文
0 0