当前位置:首页 > 在线留言 >

python基础教程_学习笔记11:魔法方法、属性和迭代器

编辑:北京飞炫空间展览展示有限公司 时间:2017-09-07 13:35:21阅读次数:2
python基础教程_学习笔记11:魔法方法、属性和迭代器 魔法方法、属性和迭代器

在python中,有的名称会在前面和后面各加上两个下划线,这种写法很特别。它表示名字有特殊含义,所以绝不要在自己的程序中使用这种名字。在python中,由这些名字组成的集合所包含的方法叫做魔法(或称特殊)方法。如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下被python调用,而几乎没有直接调用它们的必要。

准备工作

为了确保类是新型的,应该把赋值语句__metaclass__=type放在你的模块的最开始,或者(直接或间接)子类化内建类(实际上是类型)object(或其他一些新式类)。

构造方法

构造方法和其他普通方法不同的地方在于,当一个对象被创建后,会立即调用构造方法。

在python中创建一个构造方法很容易。只要把init方法的名字从简单的init修改为魔法版本__init__即可。

在python所有的魔法方法中,__init__是使用最多的一个。

重写一般方法和特殊的构造方法

如果一个方法在B类的一个实例中被调用(或一个属性被访问),但在B类中没有找到该方法,那么会去它的超类A里面找。

>>> class A:

def hello(self):

print "Hello,I'm A."

>>> class B(A):

pass

>>> a=A()

>>> b=B()

>>> a.hello()

Hello,I'm A.

>>> b.hello()

Hello,I'm A.

在子类中增加功能的最基本方式是增加方法。也可以重写一些超类的方法来自定义继承的行为。

>>> class A:

def hello(self):

print "Hello,I'm A."

>>> class B(A):

def hello(self):

print "Hello,I'm B."

>>> a=A()

>>> b=B()

>>> a.hello()

Hello,I'm A.

>>> b.hello()

Hello,I'm B.

重写是继承机制中的一个重要内容,对于构造方法尤其重要。构造方法用来初始化新创建对象的状态,大部分子类不仅要拥有自己的初始化代码,还要拥有超类的初始化代码。虽然重写的机制对于所有方法来说都是一样的,但是当处理构造方法比重写普通方法时,更可能遇到特别的问题:

如果一个类的构造方法被重写,那么就需要调用超类的构造方法,否则对象可能不能被正确地初始化。

父类:

>>> class Bird:

def __init__(self):

self.hungry=True

def eat(self):

if self.hungry:

print "Aaaaah"

self.hungry=False

else:

print "No,thanks!"

>>> b=Bird()

>>> b.eat()

Aaaaah

>>> b.eat()

No,thanks!

子类:

>>> class SongBird(Bird):

def __init__(self):

self.sound='Squawk!'

def sing(self):

print self.sound

>>> sb=SongBird()

>>> sb.sing()

Squawk!

但如果调用eat方法,就会产生一个错误:

>>> sb.eat()

Traceback (most recent call last):

File "", line 1, in

sb.eat()

File "", line 5, in eat

if self.hungry:

AttributeError: SongBird instance has no attribute 'hungry'

原因:在SongBird中,构造方法被重写,专题,但新的构造方法没有任何关于初始化hungry特性的代码。为了达到预期效果,SongBird的构造方法必须调用其超类Bird的构造方法来确保基本的初始化。

有两种方法可以达到这个目的:

调用超类方法的未绑定版本;

使用super函数;

调用未绑定的超类构造方法

上一节提出的问题的解决方法:

>>> class SongBird(Bird):

def __init__(self):

Bird.__init__(self)

self.sound='Squawk!'

def sing(self):

print self.sound

>>> sb=SongBird()

>>> sb.eat()

Aaaaah

>>> sb.eat()

No,thanks!

在调用一个实例的方法时,该方法的self参数会被自动绑定到实例上(这称为绑定方法)。如果直接调用类的方法(比如Bird.__init__)就没有实例会被绑定。这样就可以自由地提供需要的self参数。这样的方法称为未绑定方法。

使用super函数

如果不想坚守旧版python阵营的话,那么就应该使用super函数。它只能在新式类中使用,但不管怎样,都应该使用新式类。

当前的类和对象可以作为super函数的参数使用,调用函数返回的对象的任何方法都是调用超类的方法,而不是当前类的方法。那么就可以不用在SongBird的构造方法中使用Bird,而直接使用super(SongBird,self)。除此之外,__init__方法能以一个普通的绑定方法被调用。

对Bird例子的更新:

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

self.sound='Squawk!'

def sing(self):

print self.sound

>>> sb=SongBird()

>>> sb.sing()

Squawk!

>>> sb.eat()

Aaaaah

>>> sb.eat()

No,thanks!

成员访问

尽管__init__是目前为止提到的最重要的特殊方法,但还有一些其他的方法提供的作用也很重要。

基本的序列和映射的规则很简单,但如果要实现它们全部功能就需要实现很多魔法函数。

基本的序列和映射规则

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

__len__(self):这个方法应该返回集合中所含项目的数量。

对于序列来说,这是元素的个数;

对于映射来说,是键值对的数量。

如果__len__返回0(并且没有实现重写该行为的__nozero__),对象会被当作一个布尔变量中的假值(空的列表,元组,字符串和字典也一样)进行处理。

__getitem__(self.key):这个方法返回与所给键对于的值。

对于一个序列,键应该是一个0~n-1的整数,n是序列的长度;

对于映射来说,可以使用任何种类的键。

__setitem__(self,key,value):这个方法应该按一定的方式存储和key相关的value,该值随后可使用__getitem__来获取。当然,只能为可以修改的对象定义这个方法。

__delitem__(self,key):这个方法在对一部分对象使用del语句时被调用,同时必须删除和元素相关的键。这个方法也是为可修改的对象定义的(并不是删除全部的对象,而只删除一些需要移除的元素)。

属性

访问器是一个简单的方法,它能够使用getHeight、setHeight这样的名字来得到或重绑定一些特性。

python能隐藏访问器方法,让所有特性看起来一样,这些通过访问器定义的特性被称为属性。

property函数

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:黄冈网站建设 http://huanggang.45qun.com

上一篇:为主题添加前台删除文章及评论功能 下一篇:最后一页

相关阅读