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

构造方法

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

时间: 2024-10-24 10:00:05

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

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

准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here 在这两个类中,NewStyle是新式的类,OldStyle是旧式的类,如果文件以__metaclass__ = type 开始,那么两个类都是新式类. 构造方法 构造方法,当一个对象被创建后,会立即调用构造方法.Python中创建一个构造方法,只要把init方法的名字从简单的init修改成__init__

Python基础教程读书笔记

1.字符串的定义,单双引号一样,可以使用转义\ 2.拼接字符串str1+str2 3.转换成字符串 str(1000000000000000L)->'1000000000000000' repr(100000000000000000L)->'100000000000000000L' repr是会保留原值的一个操作 4.raw_input("valus :") 一般接收用户输入使用此方法 5.多行字符串或长字符串可以使用'''val'''或"""

Python基础教程---读书笔记三

原文链接:http://www.faceye.net/search/144443.html 1. 所有的标准序列操作都使用于字符串,记住字符串不可改变. 2. 字符串格式化:标记转换说明符(%),如果字符串本身包含%,用%%代替. 3. 字符串格式化转换标志:-表示左对齐:+表示在转换值前加正负号:""(空白字符)表示正数之前保留空格:0表示转换值若位数不够用0填充. 4. find(str, begin_index, end_index): 返回子串所在位置最左端索引,没有找到返回-

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

SQL Server2012 T-SQL基础教程--读书笔记(5-7章) SqlServer T-SQL 示例数据库:点我 Chapter 05 表表达式 5.1 派生表 5.1.1 分配列别名 5.1.2 使用参数 5.1.3 嵌套 5.1.4 多个引用 5.2 公用表表达式 5.2.1 分别列别名 5.2.2 使用参数 5.2.3 定义多个CTE 5.2.4 CTE的多次引用 5.2.5 递归CTE 5.3 视图 5.3.1 视图和ORDER BY 子句 5.3.2 视图选项 5.4 内嵌表

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

SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1.2 INSERT SELECT 语句 8.1.3 INSERT EXEC 语句 8.1.4 SELECT INTO 语句 8.1.5 BULK INSERT 语句 8.1.6 标识列属性和序列对象 8.1.6.1 标识列属性 8.1.6.2 序列对象 8.2 删除数据 8.2.1 DELETE 语

SQL Server2012 T-SQL基础教程--读书笔记

SQL Server2012 T-SQL基础教程--读书笔记 SqlServer Chapter 01 T-SQL 查询和编程背景 1.3 创建表和定义数据的完整性 1.3.1 创建表 1.3.2 定义数据的完整性 1. 主键约束 2. 唯一约束 3. 外键束约 4. CHECK约束 5. 默认约束 Chapter 02 单表查询 2.1 SELECT 语句元素 2.1.7 TOP和OFFSET-FETCH 1. TOP筛选 2. OFFSET-FETCH 2.1.8 开窗函数速览 2.2 谓词

Python基础教程(第九章 魔法方法、属性和迭代器)

本文内容全部出自<Python基础教程>第二版,在此分享自己的学习之路. ______欢迎转载:http://www.cnblogs.com/Marlowes/p/5437223.html______ Created on Marlowes 在Python中,有的名称会在前面和后面都加上两个下划线,这种写法很特别.前面几章中已经出现过一些这样的名称(如__future__),这种拼写表示名字有特殊含义,所以绝不要在自己的程序中使用这样的名字.在Python中,由这些名字组成的集合所包含的方法称

&lt;&lt;Python基础教程&gt;&gt;学习笔记之|第01章|基础知识

本学习笔记主要用要记录下学习<<Python基础教程>>过程中的一些Key Point,或自己没怎么搞明白的内容,可能有点杂乱,但比较实用,查找起来也方便. 第01章:基础知识 ------ Jython:      Python的Java实现,运行在JVM中,相对稳定,但落后于Python,当前版本2.5,在TA(Python+Robot)会用到 IronPython:  Python的C#实现,运行在Common Language Runtime,速度比Python要快 >

Python基础教程(第六章 抽象)

本文内容全部出自<Python基础教程>第二版,在此分享自己的学习之路. ______欢迎转载:http://www.cnblogs.com/Marlowes/p/5351415.html______ Created on Xu Hoo 本章将会介绍如何将语句组织成函数,这样,你可以告诉计算机如何做事,并且只需要告诉一次.有了函数以后,就不必反反复复像计算机传递同样的具体指令了.本章还会详细介绍参数(parameter)和作用域(scope)的概念,以及地柜的概念及其在程序中的用途. 6.1