<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 title
Step1:  对于变量x来说，不需要知道它是字符串还是列表，就可以调用它的count方法—不用管它是什么类型（只要提供一个字符作为参数即可）。  
任何不知道对象到底是什么类型，但是又要对对象“做点什么”的时候，都会用到多态。这不仅限于方法，很多内建运算符和函数都有多态的性质：
Step2:  1.2 封装
封装是可以不关心对象是如何构建的而直接进行使用。如何将变量“封装”在对象内？可以将其作为属性（attribute）存储。正如方法一样，属性是对象内部的变量。  
对象有它自己的状态（state），对象的状态由它的属性（比如名称）来描述。对象的方法可以改变它的属性。
1.3 继承
如果已经有了一个类，而又想建立一个非常类似的呢？新的类可能只是添加几个方法。这时就会用到继承。
2 类和类型
类将它视为种类或类型的同义词，代表对象的集合。类的主要任务是定义它的实例会用到的方法。所有的对象都属于某一个类，称为类的实例。当一个对象所属的类是另外一个对象所属类的子集时，前者就被称为后者的子类（subclass），所以“百灵鸟类”是“鸟类”的子类。相反，“鸟类”是“百灵鸟类”的父类（superclass）。    
Python中，习惯上使用单数名词，并且首字母大写，比如Bird和Lark，来描述对象的类。
2.1 创建自己的类
先来看一个简单的类：
Step3:  注意 尽管可能使用的是新版的Python，但一些功能不会在旧式类上起作用。为了确保类是新型的，需要在模块或者脚本开始的地方放置赋值语句__metaclass__=type，或者继承新式类（比如object类，也就是子类化内建类object）。新式类必然包含了更多的功能，也是之后推荐的写法，从写法上区分的话，如果当前类或者父类继承了object类，那么该类便是新式类。
在调用foo的setName和greet函数时，foo自动将自己作为第一个参数传人函数中—因此形象地命名为self。显然这就是self的用处和存在的必要性。没有它，成员方法就没法访问它们要对其属性进行操作的对象本身了。  
属性是可以在外部访问的：
Step4:  2.2 属性和方法
self参数事实上正是方法和函数的区别。方法将它们的第一个参数绑定到所属的实例上，因此这个参数可以不必提供。   
属性只是作为对象的一部分变量，方法则是存储在对象内的函数。
2.2.1 私有化     
默认情况下，程序可以从外部访问一个对象的属性。但是有时候需要使用私有属性，这是外部对象无法访问的，但是通过getName和setName等访问器（accessor）能够访问这些私有属性。
为了让方法或者属性变为私有，只要在它的名字前面加上双下划线即可：
Step5:  现在__inaccessible从外界是无法访问的，而在内部还能使用(比如从accessible)访问：
Step6:  类的内部定义中，所有以双下划线开始的名字（方法或属性）都被“翻译”成前面加上单下划线和类名的形式。在了解了这些幕后的事情后，实际上还是能在类外访问这些私有方法，尽管不应该这么做：
Step7:  简而言之，确保其他人不会访问对象的方法和属性是不可能的，但是通过这类“名称变化术”就是他们不应该访问这些方法和属性的强有力信号。
2.2.2 访问器方法   
访问器是一个简单的方法，它能使用getHeight、setHeight这样的名字来得到或者重绑定一些属性：
Step8:  在上面的例子中，getSize和setSize方法是一个名为size的假想属性的访问器方法，size是由width和height构成的元组。如果有一天要改变类的实现，将size变成一个真正的属性，这样width和height就可以动态算出，那么就要把它们放到一个访问器方法中去。但如果有很多简单的属性，那么就不现实了。如果那么做就得写很多访问器方法。那么怎么解决呢？这就需要用到property函数。   
property函数    
property函数的使用很简单。延续上面的Rectangle类，只要增加一行代码（子类化object，或者使用__metaclass__=type）
Step9:  在新版的Rectangle中，property函数创建了一个属性size，其中访问器方法被当做参数（先是取值，然后是赋值）。
Step10:  很显然，size属性仍然取决于getSize和setSize中的计算。但它看起来就像普通的属性一样。实际上，property函数可以用fget，fset，fdel和doc-这四个参数来调用。如果没有参数，产生的属性既不可读，也不可写。如果只使用一个参数调用（一个取值方法），产生的属性是只读的。第三个参数（可选）是一个用于删除属性的方法。第四个参数（可选）是一个文档字符串。
2.2.3 特殊方法     
在Python中，有的名称（方法名）在前面和后面都加上两个下划线，比如__future__，这样拼写表示名字有特殊含义，所以绝不要在自己的程序中使用这种名字。由这些名字组成的集合所包含的方法称为特殊方法。如果对象实现了这些方法的某一个，那么这个方法会在特殊的情况下被Python调用。而几乎没有直接调用它们的必要。
(1) 构造方法
首先要讨论的第一个特殊方法是构造方法。构造方法是一个很奇怪的名字，它代表着类似于以前例子中使用过的那种名为init的初始化方法。但构造方法和其他普通方法不同的地方在于，当一个对象被创建后，会立即调用构造方法。
Step11:  (2) 重写一般方法和特殊的构造方法  
如果一个方法在B类的一个实例中被调用（或一个属性被访问），但在B类中没有找到该方法，那么就会去它的父类A里面找：
Step12:  在子类中增加功能最基本的方式就是增加方法。但是也可以重写一些父类的方法来自定义继承的行为。B类也能重写这个方法。
Step13:  重写是继承机制中的一个重要内容，但是对于构造方法尤其重要。构造方法用来初始化新创建对象的状态，大多数子类不仅要拥有自己的初始化代码，还要拥有父类的初始化代码。虽然重写的机制对于所有方法来说都是一样的，但是当重写构造方法时，更可能遇到特别的问题：如果一个类的构造方法被重写，那么就需要调用父类的构造方法，否则对象可能不会被正确的初始化。如下：
Step14:  可以看到，鸟吃过了以后，就不会再饥饿。现在考虑子类SongBird，它添加了唱歌的行为。
Step15:  因为SongBird是Bird的一个子类，它继承了eat方法，但如果调用eat方法，就会产生一个问题：
Step16:  异常很清楚地说明了错误：SongBird没有hungry属性。原因是：在SongBird中，构造方法被重写，但新的构造方法没有任何关于初始化hungry属性的代码。为了达到预期的效果，SongBird的构造方法必须调用其父类Bird的构造方法来确保进行基本的初始化。有两种方法能达到这个目的，如下： 
调用未绑定的父类构造方法
Step17:  通过将当前的实例作为self参数提供给未绑定方法，SongBird就能够使用其父类构造方法的所有实现，也就是说属性hungry能被设置。
使用super函数  
super函数只能在新式类中使用。当前的类和对象可以作为super函数的参数使用，调用函数返回的是父类的方法，而不是当前类的方法。如下：
Step22:  (3) 成员访问方法
接下来介绍一些处理对象访问的方法，这些方法允许你创建自己的序列或者映射。   
基本的序列和映射规则很简单，但如果要实现它们全部功能就需要实现很多特殊函数。下面将会说到：
基本的序列和映射规则     
序列和映射是对象的集合。为了实现它们基本的行为（规则），如果对象是不可变的（如字符串和元组）。那么就需要使用两个特殊方法，如果是可变的（列表和字典），则需要使用4个。
a. __len__(self)
Step23:  注意，没有实现__del__方法的原因是我希望删除元素是非法的：
Step24:  这个类没有__len__方法，因为它是无限长的。   
索引检查是通过用户自定义的checkIndex函数实现的。如果使用了一个非法类型的索引，就会引发TypeError异常，如果索引的类型是正确的但超出了范围，则会引起IndexError异常：
Step25:  (4) __getattr__和__setattr__   
拦截（intercept）对象的所有属性访问是可能的，这样可以用旧式类实现属性。为了在访问属性的时候可以执行代码，必须使用一些特殊方法。下面的4种方法提供了需要的功能（在旧式类中只需要后3个）
a. __getattribute__(self,name)
Step26:  注意： __setattr__方法在所涉及的属性不是size时也会被调用。如果属性是size，那么就像前面那样执行操作，否则就要使用特殊方法__dict__，该方法包含一个字典，字典里是所有实例的属性；   
__getattr__方法只在普通的属性没有被找到的时候调用。
(5) 迭代器    
迭代的意思是重复做一些事很多次—就像在循环中做的那样。到现在为止只有在for循环中对序列和字典进行迭代，但实际上也能对其他的对象进行迭代：实现__iter__特殊方法的对象。   
__iter__方法返回一个迭代器（iterator），所谓的迭代器就是具有next方法（这个方法在调用时不需要任何参数）的对象。在调用next方法时，迭代器会返回它的下一个值。     
迭代规则的关键是什么？为什么不使用列表？因为列表的杀伤力太大。如果有可以一个接一个地计算值的函数，那么在使用时可能是计算一个值时获取一个值-而不是通过列表一次性获取所有值。如果有很多值，列表就会占用太多的内存。另外，使用迭代器更通用、更简单、更优雅。让我们看看一个不使用列表的例子，因为要用的话，列表的长度必须无限。    
这里的“列表”是一个斐波那契数列。使用的迭代器如下：
Step27:  在很多情况下，__iter__被放到会在for循环中使用的对象中。  
注意 正式的说法是，一个实现了__iter__方法的对象是可迭代的，一个实现了next方法的对象则是迭代器。    
内建函数iter可以从可迭代的对象中获得迭代器：
Step28:  从迭代器中得到序列： 
使用list函数显式地将迭代器转化为列表。
Step29:  2.3 类的命名空间
所有位于class语句中的代码都在特殊的命名空间中执行—类命名空间。这个命名空间可由类内所有成员访问。
Step30:  从上可以看出，类的定义其实就是执行代码块，这一点很有用，比如，在类的定义区并不只限使用def语句：
Step31:  上面的代码中，在类作用域内定义了一个可供所有成员（实例）访问的变量，用来计算类的成员数量。  
就像方法一样，类作用域内的变量也可以被所有实例（对象）访问：
Step32:  那么在实例中重绑定members属性呢？
Step33:  2.4 继承父类
子类可以扩展父类的定义。将其他类名写在class语句后的圆括号内就可以继承父类：
Step34:  Filter类的用处在于它可以用作其他类的父类，比如SPAMFilter类，可以将序列中“SPAM”过滤出去。
Step35:  2.4.1 子类化列表，字典和字符串   
如果希望实现一个和内建对象类型（例如列表，字符串和字典）行为相似的序列或映射，可以使用子类化内建类型。   
注意 当子类化一个内建类型，比如list的时候，也就间接的将object子类化了。因此该类就自动成为新式类，意味着可以使用像super函数这样的特性了。    
看看下面的例子-带有访问计数的列表。
Step36:  CounterList类严重依赖于它的子类化父类（list）的行为。CounterList类没有重写任何的方法，能直接调用列表的任何方法（如append、extend、index）。在两个被重写的方法中，super方法被用来调用相应的父类的方法，只有在__init__中添加了所需的初始化counter属性的行为，并在__getitem__中更新了counter属性。
Step37:  可以看到，CounterList在很多方面和列表的作用一样，但它有一个counter属性（被初始化为0），每次列表元素被访问时，它都会自增。
2.5 调查继承
如果想要查看一个类是否是另一个的子类，可以使用内建的issubclass函数：
Step38:  如果想要知道已知类的父类(们)，可以直接使用它的特殊属性__bases__：
Step39:  同样，还能使用isinstance函数检测一个对象是否是一个类的实例：
Step40:  如果只想知道一个对象属于哪个类，可以使用__class__属性或type函数：
Step41:  2.6 多个父类
一个类的父类可能多于一个，如下：
Step42:  子类（TalkingCalculator）自己不做任何事，它从自己的父类继承所有的行为。这样它就成了会说话的计算器（talking calculator）。
Step43:  这种行为称为多重继承（multiple inheritance），是个非常有用的工具。   
一般来说，对于对象不用探讨过深。程序员可以靠多态调用自己需要的方法。不过如果想要知道对象到底有什么方法和属性，有些函数可以帮助完成这项工作。如下可以检查对象的方法或属性是否已经存在：
Step44:  如果要查看对象内所有存储的值，那么可以使用__dict__属性。
Step45:  3 生成器
生成器是Python新引入的概念。生成器是一种普遍的函数语法定义的迭代器。接下来介绍怎么创建和使用生成器，了解它的内部机制。
3.1 创建生成器
创建一个生成器就像创建函数一样简单。首先我们创建一个可以展开嵌套列表的函数。参数是一个列表：
Step46:  任何包含yield语句的函数称为生成器。除了名字不同以外，它的行为和普通的函数也有很大的差别。这就在于它不像return语句那样返回值，而是每次产生一个值。每次产生一个值（使用yield语句），函数就会被冻结：即函数停在那点等待被激活。函数被激活后就从停止的那点开始执行。   
接下来可以通过在生成器上迭代来使用所有的值：
Step47:  从上可以看到，试图对一个数值5进行迭代会引发一个TypeError异常。   
生成器由两部分组成：生成器的函数和生成器的迭代器。生成器的函数是用def语句定义的，包含yield部分，生成器的迭代器是这个函数返回的部分。
Step48:  3.2 递归生成器
如果要处理任意层的嵌套该怎么办？每次嵌套需要增加一个for循环，但因为不知道有几层嵌套，所以必须把解决方案变得更灵活。这就需要用到递归：
Step49:  当flatten被调用时，有两种可能性（处理递归时大部分都是这种情况）：基本情况和需要递归的情况。在基本的情况中，函数被告知展开一个元素（比如一个数字），这种情况下，for循环会引发一个TypeError异常（因为试图对一个数字进行迭代），生成器会产生一个元素。如果展开的是一个列表，那么就要进行特殊处理。程序必须遍历所有的子列表，并对他们调用flatten。然后使用另一个for循环来产生被展开的子列表的所有元素。
<ASSISTANT_TASK:>
Python Code:
'abc'.count('a')
[1,2,'a'].count('a')
Explanation: title: 对象
create: 2016.12.7
modified: 2016.12.7
tags: python 
      多态 
      封装
      方法
      5
[TOC]
之前介绍了Python主要的内建对象类型（数字int、字符串str、列表list、元组tuple和字典dict），以及内建函数和标准库的用法，还有自定义函数的方式。接下来将介绍如何创建自己的对象？
为什么要自定义对象呢？使用字典、序列、数字和字符串来创建函数，完成这项工作还不够吗？这样做当然可以，但是创建自己的对象（尤其是类型或者被称为类的对象）是Python的核心概念，事实上，Python被称为面向对象的语言（和C++、Java一样）。接下来会介绍如何创建对象，以及多态、封装、方法、属性、父类以及继承的概念。
1 对象的魔力
对象可以看做数据（属性）以及一系列可以存取、操作这些数据的方法所组成的集合。使用对象替代全局变量和函数的原因可能有很多，其中对象最重要的优点如下：
1.1 多态
多态（Polymorphism）意味着就算不知道变量所引用的对象类型是什么，还是能对它进行操作，而它会根据对象（或类）类型的不同而表现出不同的行为。
End of explanation
1+2
'Fish '+'license'
Explanation: 对于变量x来说，不需要知道它是字符串还是列表，就可以调用它的count方法—不用管它是什么类型（只要提供一个字符作为参数即可）。  
任何不知道对象到底是什么类型，但是又要对对象“做点什么”的时候，都会用到多态。这不仅限于方法，很多内建运算符和函数都有多态的性质：
End of explanation
__metaclass__=type   #确定使用新式类
class Person:
    def setName(self, name):
        self.name=name
    def getName(self):
        return self.name
    def greet(self):
        print "Hello, world! I'm %s" % self.name
foo=Person()
foo.setName('Luke Skywalker')
foo.greet()
Explanation: 1.2 封装
封装是可以不关心对象是如何构建的而直接进行使用。如何将变量“封装”在对象内？可以将其作为属性（attribute）存储。正如方法一样，属性是对象内部的变量。  
对象有它自己的状态（state），对象的状态由它的属性（比如名称）来描述。对象的方法可以改变它的属性。
1.3 继承
如果已经有了一个类，而又想建立一个非常类似的呢？新的类可能只是添加几个方法。这时就会用到继承。
2 类和类型
类将它视为种类或类型的同义词，代表对象的集合。类的主要任务是定义它的实例会用到的方法。所有的对象都属于某一个类，称为类的实例。当一个对象所属的类是另外一个对象所属类的子集时，前者就被称为后者的子类（subclass），所以“百灵鸟类”是“鸟类”的子类。相反，“鸟类”是“百灵鸟类”的父类（superclass）。    
Python中，习惯上使用单数名词，并且首字母大写，比如Bird和Lark，来描述对象的类。
2.1 创建自己的类
先来看一个简单的类：
End of explanation
foo.name
Explanation: 注意 尽管可能使用的是新版的Python，但一些功能不会在旧式类上起作用。为了确保类是新型的，需要在模块或者脚本开始的地方放置赋值语句__metaclass__=type，或者继承新式类（比如object类，也就是子类化内建类object）。新式类必然包含了更多的功能，也是之后推荐的写法，从写法上区分的话，如果当前类或者父类继承了object类，那么该类便是新式类。
在调用foo的setName和greet函数时，foo自动将自己作为第一个参数传人函数中—因此形象地命名为self。显然这就是self的用处和存在的必要性。没有它，成员方法就没法访问它们要对其属性进行操作的对象本身了。  
属性是可以在外部访问的：
End of explanation
class Secretive:
    def __inaccessible(self):
        print "Hello, world!"
    def accessible(self):
        print "The secret message is: "
        self.__inaccessible()
Explanation: 2.2 属性和方法
self参数事实上正是方法和函数的区别。方法将它们的第一个参数绑定到所属的实例上，因此这个参数可以不必提供。   
属性只是作为对象的一部分变量，方法则是存储在对象内的函数。
2.2.1 私有化     
默认情况下，程序可以从外部访问一个对象的属性。但是有时候需要使用私有属性，这是外部对象无法访问的，但是通过getName和setName等访问器（accessor）能够访问这些私有属性。
为了让方法或者属性变为私有，只要在它的名字前面加上双下划线即可：
End of explanation
s=Secretive()
s.__inaccessible()
s.accessible()
Explanation: 现在__inaccessible从外界是无法访问的，而在内部还能使用(比如从accessible)访问：
End of explanation
s._Secretive__inaccessible()
Explanation: 类的内部定义中，所有以双下划线开始的名字（方法或属性）都被“翻译”成前面加上单下划线和类名的形式。在了解了这些幕后的事情后，实际上还是能在类外访问这些私有方法，尽管不应该这么做：
End of explanation
class Rectangle:
    def __inf__(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
r.getSize()
r.setSize((150,100))
r.width
Explanation: 简而言之，确保其他人不会访问对象的方法和属性是不可能的，但是通过这类“名称变化术”就是他们不应该访问这些方法和属性的强有力信号。
2.2.2 访问器方法   
访问器是一个简单的方法，它能使用getHeight、setHeight这样的名字来得到或者重绑定一些属性：
End of explanation
__metaclass__=type
class Rectangle:
    def __inf__(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)
Explanation: 在上面的例子中，getSize和setSize方法是一个名为size的假想属性的访问器方法，size是由width和height构成的元组。如果有一天要改变类的实现，将size变成一个真正的属性，这样width和height就可以动态算出，那么就要把它们放到一个访问器方法中去。但如果有很多简单的属性，那么就不现实了。如果那么做就得写很多访问器方法。那么怎么解决呢？这就需要用到property函数。   
property函数    
property函数的使用很简单。延续上面的Rectangle类，只要增加一行代码（子类化object，或者使用__metaclass__=type）:
End of explanation
w=Rectangle()
w.width=10
w.height=5
w.size
w.size=150,100
w.width
Explanation: 在新版的Rectangle中，property函数创建了一个属性size，其中访问器方法被当做参数（先是取值，然后是赋值）。
End of explanation
class FooBar:
    def __init__(self):
        self.somevar=42
f=FooBar()
f.somevar
Explanation: 很显然，size属性仍然取决于getSize和setSize中的计算。但它看起来就像普通的属性一样。实际上，property函数可以用fget，fset，fdel和doc-这四个参数来调用。如果没有参数，产生的属性既不可读，也不可写。如果只使用一个参数调用（一个取值方法），产生的属性是只读的。第三个参数（可选）是一个用于删除属性的方法。第四个参数（可选）是一个文档字符串。
2.2.3 特殊方法     
在Python中，有的名称（方法名）在前面和后面都加上两个下划线，比如__future__，这样拼写表示名字有特殊含义，所以绝不要在自己的程序中使用这种名字。由这些名字组成的集合所包含的方法称为特殊方法。如果对象实现了这些方法的某一个，那么这个方法会在特殊的情况下被Python调用。而几乎没有直接调用它们的必要。
(1) 构造方法
首先要讨论的第一个特殊方法是构造方法。构造方法是一个很奇怪的名字，它代表着类似于以前例子中使用过的那种名为init的初始化方法。但构造方法和其他普通方法不同的地方在于，当一个对象被创建后，会立即调用构造方法。
End of explanation
class A:
    def hello(self):
        print "hello, I'm A"
class B(A):
    pass
a=A()
b=B()
a.hello()
b.hello()
Explanation: (2) 重写一般方法和特殊的构造方法  
如果一个方法在B类的一个实例中被调用（或一个属性被访问），但在B类中没有找到该方法，那么就会去它的父类A里面找：
End of explanation
class B(A):
    def hello(self):
        print "hello, I'm B"
b=B()
b.hello()  
Explanation: 在子类中增加功能最基本的方式就是增加方法。但是也可以重写一些父类的方法来自定义继承的行为。B类也能重写这个方法。
End of explanation
class Bird:
    def __init__(self):
        self.hungry=True
    def eat(self):
        if self.hungry:
            print 'Aaaah...'
            self.hungry=False
        else:
            print 'No,thanks!'
b=Bird()
b.eat()
b.eat()
Explanation: 重写是继承机制中的一个重要内容，但是对于构造方法尤其重要。构造方法用来初始化新创建对象的状态，大多数子类不仅要拥有自己的初始化代码，还要拥有父类的初始化代码。虽然重写的机制对于所有方法来说都是一样的，但是当重写构造方法时，更可能遇到特别的问题：如果一个类的构造方法被重写，那么就需要调用父类的构造方法，否则对象可能不会被正确的初始化。如下：
End of explanation
class SongBird(Bird):
    def __init__(self):
        self.sound='Squawk!'
    def sing(self):
        print self.sound
sb=SongBird()
sb.sing()
Explanation: 可以看到，鸟吃过了以后，就不会再饥饿。现在考虑子类SongBird，它添加了唱歌的行为。
End of explanation
sb.eat()
Explanation: 因为SongBird是Bird的一个子类，它继承了eat方法，但如果调用eat方法，就会产生一个问题：
End of explanation
class SongBird(Bird):
    def __init__(self):
        Bird.__init__(self)
        self.sound='Squawk!'
    def sing(self):
        print self.sound
sb=SongBird()
sb.sing()
sb.eat()
sb.eat()
Explanation: 异常很清楚地说明了错误：SongBird没有hungry属性。原因是：在SongBird中，构造方法被重写，但新的构造方法没有任何关于初始化hungry属性的代码。为了达到预期的效果，SongBird的构造方法必须调用其父类Bird的构造方法来确保进行基本的初始化。有两种方法能达到这个目的，如下： 
调用未绑定的父类构造方法
End of explanation
__metaclass__=type
class SongBird(Bird):
    def __init__(self):
        super(SongBird,self).__init__()
        self.sound='Squawk!'
    def sing(self):
        print self.sound
sb=SongBird()
sb.sing()
sb.eat()
sb.eat()
Explanation: 通过将当前的实例作为self参数提供给未绑定方法，SongBird就能够使用其父类构造方法的所有实现，也就是说属性hungry能被设置。
使用super函数  
super函数只能在新式类中使用。当前的类和对象可以作为super函数的参数使用，调用函数返回的是父类的方法，而不是当前类的方法。如下：
End of explanation
def checkIndex(key):
    所给的键能接受索引吗？
    为了能被接受，键应该是一个非负的整数，如果它不是一个整数，比如是字符串，会引发TypeError;
    如果它是负数，则会引发IndexError（因为序列是无限长的）。
    
    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):
        Get an item from the arithmetic sequence.
        
        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]
s[4]=2
s[4]
s[5]
Explanation: (3) 成员访问方法
接下来介绍一些处理对象访问的方法，这些方法允许你创建自己的序列或者映射。   
基本的序列和映射规则很简单，但如果要实现它们全部功能就需要实现很多特殊函数。下面将会说到：
基本的序列和映射规则     
序列和映射是对象的集合。为了实现它们基本的行为（规则），如果对象是不可变的（如字符串和元组）。那么就需要使用两个特殊方法，如果是可变的（列表和字典），则需要使用4个。
a. __len__(self):这个方法返回集合中所含对象的数量。对于序列来说，这就是元素的个数；对于映射来说，则是键-值对的数量。
b. __getitem__(self,key):这个方法返回与所给键对应的值。对于序列来说，键应该是一个0~n-1的整数（或者像后面所说的负数）；对于映射来说，可以使用任何种类的键。
c. __setitem__(self,key,value):这个方法按一定的方式存储和key关联的value，该值随后可使用 __getitem__来获取。当然，只能为可以修改的对象定义这个方法。
d. __delitem__(self,key):这个方法在对一部分对象使用del语句时被调用，同时删除和键关联的值。这个方法也是为可修改的对象定义的。     
对这些方法的附件要求：   
a. 对于一个序列来说，如果键是负整数，那么要从末尾开始计数。换句话说就是x[-n]和x[len(x)-n]是一样的；  
b. 如果键是不合适的类型（例如，对序列使用字符串作为键），会引发一个TypeError异常;    
c. 如果序列的索引是正确的类型，但超出了范围，会引发一个IndexError异常。   
让我们实践一下—看看如果创建一个无穷序列，会发生什么：
End of explanation
del s[4]
Explanation: 注意，没有实现__del__方法的原因是我希望删除元素是非法的：
End of explanation
s['four']
s[-4]
Explanation: 这个类没有__len__方法，因为它是无限长的。   
索引检查是通过用户自定义的checkIndex函数实现的。如果使用了一个非法类型的索引，就会引发TypeError异常，如果索引的类型是正确的但超出了范围，则会引起IndexError异常：
End of explanation
class Rectangle:
    def __init__(self):
        self.width=0
        self.height=0
    def __setattr__(self,name,value):
        if name =='size':
            self.width,self.height=value
        else:
            self.__dict__[name]=value
    def __getattr__(self,name):
        if name =='size':
            return self.width,self.height
        else:
            raise AttributeError
w=Rectangle()
w.size
w.__dict__
w.size=(2,6)
w.size
w.width
hasattr(w,'size')
w.age=28
w.age
w.__dict__
Explanation: (4) __getattr__和__setattr__   
拦截（intercept）对象的所有属性访问是可能的，这样可以用旧式类实现属性。为了在访问属性的时候可以执行代码，必须使用一些特殊方法。下面的4种方法提供了需要的功能（在旧式类中只需要后3个）
a. __getattribute__(self,name):当属性name被访问时自动被调用（只能在新式类中使用）；
b. __getattr__(self,name):当属性name被访问且对象没有相应的属性时被自动调用；
c. __setattr__(self,name,value): 当试图给属性name赋值时会被自动调用；
d. __delattr__(self,name): 当试图删除属性name时会被自动调用。
尽管和使用property函数相比有点复杂（而且在某些方面效率更低），但是这些特殊方法是很强大的，因为可以对处理很多属性的方法进行再编码。   
下面还是Rectangle的例子，但这次使用的是特殊方法：
End of explanation
class Fibs:
    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()
for f in fibs:
    if f>10:
        print f
        break
Explanation: 注意： __setattr__方法在所涉及的属性不是size时也会被调用。如果属性是size，那么就像前面那样执行操作，否则就要使用特殊方法__dict__，该方法包含一个字典，字典里是所有实例的属性；   
__getattr__方法只在普通的属性没有被找到的时候调用。
(5) 迭代器    
迭代的意思是重复做一些事很多次—就像在循环中做的那样。到现在为止只有在for循环中对序列和字典进行迭代，但实际上也能对其他的对象进行迭代：实现__iter__特殊方法的对象。   
__iter__方法返回一个迭代器（iterator），所谓的迭代器就是具有next方法（这个方法在调用时不需要任何参数）的对象。在调用next方法时，迭代器会返回它的下一个值。     
迭代规则的关键是什么？为什么不使用列表？因为列表的杀伤力太大。如果有可以一个接一个地计算值的函数，那么在使用时可能是计算一个值时获取一个值-而不是通过列表一次性获取所有值。如果有很多值，列表就会占用太多的内存。另外，使用迭代器更通用、更简单、更优雅。让我们看看一个不使用列表的例子，因为要用的话，列表的长度必须无限。    
这里的“列表”是一个斐波那契数列。使用的迭代器如下：
End of explanation
a=[1,2,3]
a.next()
it=iter([1,2,3])
it.next()
it.next()
Explanation: 在很多情况下，__iter__被放到会在for循环中使用的对象中。  
注意 正式的说法是，一个实现了__iter__方法的对象是可迭代的，一个实现了next方法的对象则是迭代器。    
内建函数iter可以从可迭代的对象中获得迭代器：
End of explanation
it=iter([1,2,3])
it
list(it)
Explanation: 从迭代器中得到序列： 
使用list函数显式地将迭代器转化为列表。
End of explanation
class C:
    print 'Class C being defined...'
Explanation: 2.3 类的命名空间
所有位于class语句中的代码都在特殊的命名空间中执行—类命名空间。这个命名空间可由类内所有成员访问。
End of explanation
class MemberCounter:
    members=0
    def init(self):
        MemberCounter.members+=1
m1=MemberCounter()
m1.init()
MemberCounter.members
m2=MemberCounter()
m2.init()
MemberCounter.members
Explanation: 从上可以看出，类的定义其实就是执行代码块，这一点很有用，比如，在类的定义区并不只限使用def语句：
End of explanation
m1.members
m2.members
Explanation: 上面的代码中，在类作用域内定义了一个可供所有成员（实例）访问的变量，用来计算类的成员数量。  
就像方法一样，类作用域内的变量也可以被所有实例（对象）访问：
End of explanation
m1.members='Two'
m1.members
m2.members
Explanation: 那么在实例中重绑定members属性呢？
End of explanation
class Filter:
    def init(self):
        self.blocked=[]
    def filter(self,sequence):
        return [x for x in sequence if x not in self.blocked]
class SPAMFilter(Filter):
    def init(self):
        self.blocked=['SPAM']
f=Filter()
f.init()
f.filter([1,2,3])
Explanation: 2.4 继承父类
子类可以扩展父类的定义。将其他类名写在class语句后的圆括号内就可以继承父类：
End of explanation
s=SPAMFilter()
s.init()
s.filter(['SPAM','SPAM','SPAM','SPAM','eggs','bacon'])
Explanation: Filter类的用处在于它可以用作其他类的父类，比如SPAMFilter类，可以将序列中“SPAM”过滤出去。
End of explanation
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)
Explanation: 2.4.1 子类化列表，字典和字符串   
如果希望实现一个和内建对象类型（例如列表，字符串和字典）行为相似的序列或映射，可以使用子类化内建类型。   
注意 当子类化一个内建类型，比如list的时候，也就间接的将object子类化了。因此该类就自动成为新式类，意味着可以使用像super函数这样的特性了。    
看看下面的例子-带有访问计数的列表。
End of explanation
c1=CounterList('aaa')
c1
c1=CounterList((1,2,3))
c1
c1=CounterList({'first':1,'second':2})
c1
c1=CounterList(range(10))
c1
c1.reverse()
c1
del c1[3:6]
c1
c1.counter
c1[0]+c1[1]+c1[2]
c1.counter
Explanation: CounterList类严重依赖于它的子类化父类（list）的行为。CounterList类没有重写任何的方法，能直接调用列表的任何方法（如append、extend、index）。在两个被重写的方法中，super方法被用来调用相应的父类的方法，只有在__init__中添加了所需的初始化counter属性的行为，并在__getitem__中更新了counter属性。
End of explanation
issubclass(SPAMFilter,Filter)
issubclass(Filter,SPAMFilter)
Explanation: 可以看到，CounterList在很多方面和列表的作用一样，但它有一个counter属性（被初始化为0），每次列表元素被访问时，它都会自增。
2.5 调查继承
如果想要查看一个类是否是另一个的子类，可以使用内建的issubclass函数：
End of explanation
SPAMFilter.__bases__
Filter.__bases__
Explanation: 如果想要知道已知类的父类(们)，可以直接使用它的特殊属性__bases__：
End of explanation
s=SPAMFilter()
isinstance(s,SPAMFilter)
isinstance(s,str)
Explanation: 同样，还能使用isinstance函数检测一个对象是否是一个类的实例：
End of explanation
s.__class__
type(s)
type([1,2])
Explanation: 如果只想知道一个对象属于哪个类，可以使用__class__属性或type函数：
End of explanation
class Calculator:
    def calculate(self,expression):
        self.value=eval(expression)
class Talker:
    def talk(self):
        print 'Hi,my value is ',self.value
class TalkingCalculator(Calculator,Talker):
    pass
Explanation: 2.6 多个父类
一个类的父类可能多于一个，如下：
End of explanation
tc=TalkingCalculator()
tc.calculate('1+2+3')
tc.talk()
Explanation: 子类（TalkingCalculator）自己不做任何事，它从自己的父类继承所有的行为。这样它就成了会说话的计算器（talking calculator）。
End of explanation
hasattr(tc,'talk')
hasattr(tc,'fnord')
getattr(tc,'talk','None')   #获得对象属性的值，可选择提供默认值，以便在属性不存在时使用
getattr(tc,'value','None')
setattr(tc,'name','Mr. Gumby')   #与getattr相对应的函数是setattr，用来设置对象的属性及值
tc.name
Explanation: 这种行为称为多重继承（multiple inheritance），是个非常有用的工具。   
一般来说，对于对象不用探讨过深。程序员可以靠多态调用自己需要的方法。不过如果想要知道对象到底有什么方法和属性，有些函数可以帮助完成这项工作。如下可以检查对象的方法或属性是否已经存在：
End of explanation
tc.__dict__
Explanation: 如果要查看对象内所有存储的值，那么可以使用__dict__属性。
End of explanation
def flatten(nested):
    for sublist in nested:
        for element in sublist:
            yield element
nested=[[1,2],[3,4],5]
Explanation: 3 生成器
生成器是Python新引入的概念。生成器是一种普遍的函数语法定义的迭代器。接下来介绍怎么创建和使用生成器，了解它的内部机制。
3.1 创建生成器
创建一个生成器就像创建函数一样简单。首先我们创建一个可以展开嵌套列表的函数。参数是一个列表：
End of explanation
flatten(nested)
for num in flatten(nested):
    print num
Explanation: 任何包含yield语句的函数称为生成器。除了名字不同以外，它的行为和普通的函数也有很大的差别。这就在于它不像return语句那样返回值，而是每次产生一个值。每次产生一个值（使用yield语句），函数就会被冻结：即函数停在那点等待被激活。函数被激活后就从停止的那点开始执行。   
接下来可以通过在生成器上迭代来使用所有的值：
End of explanation
nested=[[1,2],[3,4],[5]]
list(flatten(nested))
Explanation: 从上可以看到，试图对一个数值5进行迭代会引发一个TypeError异常。   
生成器由两部分组成：生成器的函数和生成器的迭代器。生成器的函数是用def语句定义的，包含yield部分，生成器的迭代器是这个函数返回的部分。
End of explanation
def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested
Explanation: 3.2 递归生成器
如果要处理任意层的嵌套该怎么办？每次嵌套需要增加一个for循环，但因为不知道有几层嵌套，所以必须把解决方案变得更灵活。这就需要用到递归：
End of explanation
list(flatten([[[1],2],3,4,[5,[6,7]],8]))
Explanation: 当flatten被调用时，有两种可能性（处理递归时大部分都是这种情况）：基本情况和需要递归的情况。在基本的情况中，函数被告知展开一个元素（比如一个数字），这种情况下，for循环会引发一个TypeError异常（因为试图对一个数字进行迭代），生成器会产生一个元素。如果展开的是一个列表，那么就要进行特殊处理。程序必须遍历所有的子列表，并对他们调用flatten。然后使用另一个for循环来产生被展开的子列表的所有元素。
End of explanation
<END_TASK>