您的位置:首页 > 编程语言 > Python开发

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

2017-11-10 22:12 871 查看
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:
    def
hello(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:
    def
hello(self):
        print"hello ,I.m A"
classB(A):
    pass
    def
hello(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
    def
eat(self):
        if
self.hungry:
            print'Aaah...'
            self.hungry=False
        else:
                print"No,thansk"
       
classSongBird(Bird):
    def
__init__(self):
        self.sound='Squawk!'
    def
sing(self):
        print
self.sound
 
sb=SongBird()
sb.sing()
sb.eat()

运行如下:

Squawk!
Traceback(most recent call last):
AttributeError:SongBird instance has no attribute 'hungry'

没有hungry属性。

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

from_pyio
import__metaclass__
__metaclass__=type
classBird:
    def
__init__(self):
        self.hungry=True
    def
eat(self):
        if
self.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!'
    def
sing(self):
        print
self.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:return
self.changed[key]
        except KeyError:
            return
self.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
    def
setSize(self,size):
        self.width,self.height=size
    def
getSize(self):
        return
self.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_pyio
import__metaclass__
__metaclass__=type
classRectangle:
    def
__init__(self):
        self.width=0
        self.height=0
    def
setSize(self,size):
        self.width,self.height=size
    def
getSize(self):
        return
self.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
    def
smeth():
        print'This is a static method'
    @classmethod
    def
cmeth(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'
            return
self.width,self.height           
        else:
            raise AttributeError
 
    def
setSize(self,size):
        self.width,self.height=size
    def
getSize(self):
        return
self.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
    def
next(self):
        self.a,self.b =
self.b,self.a+self.b
        return
self.a
    def
__iter__(self):
        return
self
 
 
fibs=Fibs()
 
forf
in fibs:
    if f>1000:
        print f
        break

输出如下:

1597

 

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

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

>>> it.next()

1

>>> it.next()

2

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

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

classTestIterator:
    value=0
    def
next(self):
        self.value+=1
        if
self.value>10:raiseStopIteration
        return
self.value
    def
__iter__(self):
        return
self
 
ti=TestIterator()
print list(ti)

输出如下:

[1, 2,3, 4, 5, 6, 7, 8, 9, 10]
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: