构造方法

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

>>> class FooBar:

...     def __init__(self):

...         self.somevar=42

...

>>> f=FooBar()

>>> f.somevar

42

给构造方法传几个参数

>>> class FooBar:

...     def __init__(self,value=42):

...         self.somevar=value

...

>>> f=FooBar('this is a constructor argument')

>>> f.somevar

'this is a constructor argument'

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

构造方法用来初始化新创建对象的状态,大多数子类不仅要拥有自己的初始化代码,还要拥有超类的初始化代码。虽然重写的机制对于所有方法来说都是一样的,但是当处理构造方法比重写普通方法时,更可能遇到特别的问题:如果一个类的构造方法被重写,那么就需要调用超类(你所继承的类)的构造方法,否则对象可能不会被正确地初始化。

>>> class Bird:

...     def __init__(self):

...         self.hungry=True

...     def eat(self):

...         if self.hungry:

...             print 'aaah...'

...             self.hungry=False

...         else:

...             print 'no thanks'

...

>>> b=Bird()

>>> b.eat()

aaah...

>>> b.eat()

no thanks

鸟吃过了以后,它就不再饥饿。现在考虑子类SongBird,它添加了唱歌的行为:

>>> class SongBird(Bird):

...     def __init__(self):

...         self.sound='Squawk'

...     def sing(self):

...         print self.sound

...

>>> s=SongBird()

>>> s.sing()

Squawk

因为SongBird是Bird的一个子类,它继承了eat方法,但如果调用eat方法,就会产生一个问题:

>>> s.eat()

Traceback (most recent call last):

File "<input>", line 1, in <module>

File "<input>", line 5, in eat

AttributeError: SongBird instance has no attribute 'hungry'

错误:SongBird没有hungry特性。原因是这样的:在SongBird中,构造方法被重写,但新的构造方法没有任何关于初始化hungry特性的代码。为了达到预期的效果,SongBird的构造方法必须调用其超类Bird的构造方法来确保进行基本的初始化。有两种方法能达到这个目的:调用超类构造方法的未绑定版本,或者使用super函数。

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

>>> class SongBird(Bird):

...     def __init__(self):

...         Bird.__init__(self)

...         self.sound='Squawk'

...     def sing(self):

...         print self.sound

...

>>> s=SongBird()

>>> s.eat()

aaah...

>>> s.eat()

no thanks

>>> s.sing()

Squawk

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

使用super函数

当前的类和对象可以作为super函数的参数使用,调用函数返回的对象的任何方法都是调用超类的方法,而不是当前类的方法。

>>> __metaclass__=type

>>> class Bird:

...     def __init__(self):

...         self.hungry=True

...     def eat(self):

...         if self.hungry:

...             print 'aaah...'

...             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

...

这个新式的版本的运行结果和旧式版本的一样

>>> s=SongBird()

>>> s.sing()

Squawk

>>> s.eat()

aaah...

>>> s.eat()

no thanks

基本的序列和映射规则

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

__len__(self):这个方法应该返回集合中所含项目的数量。对于序列来说,这就是元素的个数。对于映射来说,则是键-值对的数量。

__getitem__(self,key):这个方法返回与所给键对应的值。对于一个序列,键应该是1个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 ArithmeticSequence:

...     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]

9

>>> s[4]=2

>>> s[4]

2

>>> s[5]

11

没有实现__del__方法的原因是希望删除元素是非法的:

>>> del s[4]

Traceback (most recent call last):

File "<input>", line 1, in <module>

AttributeError: ArithmeticSequence instance has no attribute '__delitem__'

这个类没有__len__方法,因为它是无限长的。

如果使用了一个非法类型的索引,就会引发TypeError异常,如果索引的类型是正确的但超出了范围(在本例中为负数),则会引发IndexError异常:

>>> s[four]

Traceback (most recent call last):

File "<input>", line 1, in <module>

NameError: name 'four' is not defined

>>> s[-4]

Traceback (most recent call last):

File "<input>", line 1, in <module>

File "<input>", line 7, in __getitem__

File "<input>", line 3, in checkIndex

IndexError

子类化列表,字典和字符串

例子----带有访问计数的列表:

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

...

CounterList类严重依赖于它的子类化超类(list)的行为CounterList类没有重写任何的方法(和append  extend, index一样)都能被直接使用。在两个被重写的方法中,super方法被用来调用相应的超类的方法,只在__init__中添加了所需的初始化counter特性的行为,并在__getitem__中更新了counter特性。

>>> c1=CounterList(range(10))

>>> c1

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

>>> c1.reverse()

>>> c1

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

>>> del c1[3:6]

>>> c1

[9, 8, 7, 3, 2, 1, 0]

>>> c1[4]+c1[2]

9

>>> c1.counter

2

CounterList在很多方面和列表的作用一样,但它有一个counter特性(被初始化为0),每次列表元素被访问时,它都会自增,所以在执行加法c1[4]+c1[2〕后,这个值自增两次,变为2.

《Python基础教程》 读书笔记 第九章 魔法方法、属性和迭代器(上)的更多相关文章

  1. 《Python基础教程读书笔记》

    第1章 快速构造:基础知识 1.2交互式构造器 不强制分号,一行就是一行.可以加上分号 1.4数字和表达式 加.减.乘.除.整除.求余.指数.取反(-例如-2**2,**的优先级比-大) from _ ...

  2. 《Python基础教程(第二版)》学习笔记 -> 第九章 魔法方法、属性和迭代器

    准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here ...

  3. Python基础教程 读书笔记(2)第二章 列表和元组

    2.1序列概览 列表和元组的主要区别在于,列表可以修改,元组则不能.也就是说如果要根据要求来添加元素,那么列表可能会更好用;而出于某些原因,序列不能修改的时候,使用元组则更为合适.使用后者的理由通常是 ...

  4. SQL Server2012 T-SQL基础教程--读书笔记(1-4章)

    SQL Server2012 T-SQL基础教程--读书笔记(1-4章) SqlServer T-SQL 示例数据库:点我 Chapter 01 T-SQL 查询和编程背景 1.3 创建表和定义数据的 ...

  5. SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)

    SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1 ...

  6. SQL Server2012 T-SQL基础教程--读书笔记(5-7章)

    SQL Server2012 T-SQL基础教程--读书笔记(5-7章) SqlServer T-SQL 示例数据库:点我 Chapter 05 表表达式 5.1 派生表 5.1.1 分配列别名 5. ...

  7. Python基础教程学习笔记:第一章 基础知识

    Python基础教程 第二版 学习笔记 1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入“p ...

  8. python基础学习之类的继承、魔法方法

    什么是继承 即类A可以使用类B的方法,即B是A的父类,A是B的子类,AB之间是继承关系 class Father():  # 父类 def __init__(self,name,age): self. ...

  9. 《Python基础教程》第2章读书笔记(1)

    # -*- coding:utf-8 -*- #最基本的数据结构:序列,索引从0开始 #python包括6种内建的序列 #最常用的序列包括:列表,元祖 #列表 edward = ['Edward Gu ...

随机推荐

  1. 可移植的配置visual studio工程第三方库

    现在编程有太多的好用的第三方库,例如 计算机视觉方面的opencv c++的扩充库boost 特殊的第三方库,相机库,通讯库等 使用这些库给我们带来了极大的便利,同时也有很多困扰.这个工程在我电脑上明 ...

  2. Yet Another Number Sequence

    题意: $F_0 = 0, F_1 = 1, F_n = F_{n-1} + F_{n-2}$ 求解$\sum_{i=1}^n{ F_i i^K } \  mod \  10^9+7$. 解法: 记$ ...

  3. ShutdownHook作用

    源地址:http://kim-miao.iteye.com/blog/1662550 void java.lang.Runtime.addShutdownHook(Thread hook) 该方法用来 ...

  4. GIL 已经被杀死了么?

    GIL 已经被杀死了么? 本文原创并首发于公众号[Python猫],未经授权,请勿转载. 原文地址:https://mp.weixin.qq.com/s/8KvQemz0SWq2hw-2aBPv2Q ...

  5. 利用YYLabel 进行图文混排+高度计算

    利用YYLabel 进行图文混排+高度计算 1.项目需求: 用一个控件显示图片和文字,并且依据图片和文字动态计算控件的高度. 2.方案: 利用YYLabel控件和属性字符串处理. 注:(在使用YYLa ...

  6. HTML5 中的meter 标签的样式设置

    meter { -webkit-appearance: none; position: relative; display: block; margin: 8px auto; width: 100px ...

  7. hrbust1444 逃脱 【BFS】

    Description  这是mengxiang000和Tabris来到幼儿园的第四天,幼儿园老师在值班的时候突然发现幼儿园某处发生火灾,而且火势蔓延极快,老师在第一时间就发出了警报,位于幼儿园某处的 ...

  8. unity从模型中抽取动画文件(animation)

    http://www.cnblogs.com/leng-yuye/archive/2013/01/11/2856144.html 由于模型是由第三方的软件制作的,用unity不能直接编辑模型里的动画文 ...

  9. unity5之代码创建状态机,玩的666

    http://blog.csdn.net/litaog00/article/details/50483189 最近做项目的时候用到了状态机,网上搜了一下帖子,大部分都是简单介绍使用方法的,讲解的详细的 ...

  10. valgrind 使用入门

    近期在学习使用valgrind 来定位性能问题,记录一下整个操作过程以及涉及到的工具 一般在机器上都会预装valgrind 工具 使用callgrind 工具检查程序的调用情况,例如使用valgrin ...