<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 抽象数据类型和 Python 类
抽象数据类型
Abstract data Type, ADT
数据类型
Python 基本数据类型：逻辑类型bool，数值类型int和float，字符串str和组合数据类型
str, tuple, frozenset 是不变数据类型，list, set, dict 是可变数据类型
Python类
在Python中，利用class定义（类定义）实现抽象数据类型。
Python 中基于 class 的编程技术，称为面向对象技术
类定义机制用于定义程序里需要的类型，定义好的一个类就像一个系统内部类型，可以产生该类型的对象（实例），实例对象具有这个类描述的行为。
类里定义的变量和函数称为这个类的属性，属性包括：数据属性和方法
执行一个类定义将创建一个类对象（类本身就是一个对象），这种对象主要支持两种操作：属性访问和实例化（创建这个类的实例对象）
数据属性
数据属性分为类数据属性和实例数据属性
类数据属性属于类本身，可以通过类名进行访问/修改
类数据属性也可以被类的所有实例访问/修改
在类定义之后，可以通过类名动态添加类数据属性，新增的类属性也被类和所有实例共有
实例数据属性只能通过实例访问
在实例生成后，还可以动态添加实例数据属性，但是这些实例数据属性只属于该实例
注意：
在类定义的方法中调用类数据属性时，要用引用的方式，如：Student.skills
虽然通过实例可以访问类属性，但是，不建议这么做，最好还是通过类名来访问类属性，从而避免属性隐藏带来的不必要麻烦。
Step2:  特殊的类属性
|类属性    |    含义    |
|
Step3:  方法
实例方法
静态方法
类方法
实例方法
如果希望类里的一个函数能作为该类实例的方法，这个函数至少需要有一个表示其调用对象的形参，放在函数定义参数表的第一个位置，通常取名self（可以用任何名字，这只是Python社区的习惯）。
初始化方法是一种特殊的实例方法。
作用：新建一个实例对象时，自动调用初始化方法，给实例对象绑定一些属性。
Step4:  定义一个Animal类，初始化方法把形参name赋值给实例对象数据属性name
通过animal.get_name()调用实例方法，实例对象animal作为get_name的第一个实参约束到函数的第一个形参self，所以在实例方法定义中对self的操作都是对调用这个实例方法的实例的操作。
总结：实例方法能够对实例对象操作，在定义时至少有一个形参，其中第一个形参通常是self，当实例对象调用方法时，这个对象就被约束到self上（初始化时也类似）。
@staticmethod 静态方法
静态方法就是在类里面定义的普通函数，但根据信息局部化的原则，局部使用的功能不应该定义为全局函数，所以把它定义在类内部。
静态方法的参数表 不应该有 self 参数，在其他方面也没有任何限制.
它不会对类的实例进行操作，但类和类的实例都可以调用静态方法，可以从其定义所在类的名字出发通过圆点形式调用，也可以从该类的对象（实例）通过圆点形式调用。
Step5:  @classmethod 类方法
类方法和实例方法一样，都有参数限制，在定义类方法时必须有一个表示其调用类的参数，习惯用 cls 作为参数名，通常用类方法实现与本类所有对象有关的操作。类和实例对象都能调用类方法。
Step6:  私有变量
官方教程：
"Private" instance variables that cannot be accessed except from inside an object don’t exist in Python, However, there is a convention that is followed by most Python code
Step7:  通常在类中定义方法去访问和修改这些私有变量。
数据封装，确保了外部代码不能随意修改对象内部的状态，通过访问限制的保护，代码更加健壮。
通过定义的方法修改参数，可以对参数做检查，同样使代码健壮。
Step8:  约定把以一个下划线开头的名字做为实例对象内部的东西，永远不从对象的外部访问他们
两个下划线开头（不是以两个下划线结尾），在类之外采用属性访问方式直接写这个名字将无法找到他
注意：以两个下划线开头和结尾的是特殊变量（如：_doc_），特殊变量是可以直接访问的。
继承
基于类和对象的程序设计成为面向对象的程序设计（OOP）
定义类
创建实例对象
调用对象的方法完成计算工作，包括对象间的信息交换
基类 派生类
替换原理：一个类的实例对象的上下文可以使用其派生类的实例对象
Python内置函数issubclass检查两个类是否有继承关系
Step9:  注意：
说明文档对于类，函数/方法，以及模块来说是唯一的，也就是说__doc__属性是不能从父类中继承来的。
Step10:  方法查找
一个实例对象调用方法，Python解释器需要确定调用的函数（在哪个类里定义的函数），这个过程沿着继承关系进行。 
有一点需要注意：
动态约束
静态约束
在程序设计领域，通过动态约束确定调用关系的函数称为虚函数
Step11:  标准函数 super()
不要一说到 super 就想到父类！super 指的是 MRO 中的下一个类！
MRO
Step12:  首先建立一个实例对象，会自动调用初始化方法，为什么 B 的 init 会被调用：因为 D 没有定义 init，所以会在 MRO 中找下一个类，去查看它有没有定义 init，也就是去调用 B 的 init。
在 MRO 中，基类永远出现在派生类后面，如果有多个基类，基类的相对顺序保持不变
上面的例子的继承链（MRO顺序）：[D, B, C, Root, Object]
_slots_
当我们通过一个类创建了实例之后，仍然可以给实例动态添加属性，但是这些属性只属于这个实例。
有些时候，我们可以需要限制类实例对象的属性，这时就要用到类中的__slots__属性了。__slots__属性对于一个tuple，只有这个tuple中出现的属性可以被类实例使用。
使用__slots__要注意，__slots__定义的属性仅对当前类的实例起作用，对继承的子类实例是不起作用的
如果子类本身也有_slots__属性，子类的属性就是自身的__slots__加上父类的__slots_
实例不超过万级别的类，__slots__是不太值得使用的。
Step13:  _new_
编程实践
通常把类的定义写在模块最外层，这样定义的类在整个模块（.py文件）都能使用，而且允许其他模块通过 import 语句导入和使用
Python 异常
Python 的异常都是类（class），运行时产生异常就是生成相应类的实例对象，异常处理机制完全基于面向对象的概念和性质。
所有异常类的基类 BaseException，其最主要的子类是 Exception，内置异常类都是从这个类直接或间接派生。
捕捉异常语句：try
<ASSISTANT_TASK:>
Python Code:
class Student(object):
    skills = []
    def __init__(self, name):
        self.name = name
        
stu = Student('ly')
print Student.skills    # 访问类数据属性
Student.skills.append('Python')
print Student.skills
print stu.skills            # 通过实例也能访问类数据属性
print dir(Student)
Student.age = 25       # 通过类名动态添加类数据属性
print dir(Student)
print stu.age
Explanation: 抽象数据类型和 Python 类
抽象数据类型
Abstract data Type, ADT
数据类型
Python 基本数据类型：逻辑类型bool，数值类型int和float，字符串str和组合数据类型
str, tuple, frozenset 是不变数据类型，list, set, dict 是可变数据类型
Python类
在Python中，利用class定义（类定义）实现抽象数据类型。
Python 中基于 class 的编程技术，称为面向对象技术
类定义机制用于定义程序里需要的类型，定义好的一个类就像一个系统内部类型，可以产生该类型的对象（实例），实例对象具有这个类描述的行为。
类里定义的变量和函数称为这个类的属性，属性包括：数据属性和方法
执行一个类定义将创建一个类对象（类本身就是一个对象），这种对象主要支持两种操作：属性访问和实例化（创建这个类的实例对象）
数据属性
数据属性分为类数据属性和实例数据属性
类数据属性属于类本身，可以通过类名进行访问/修改
类数据属性也可以被类的所有实例访问/修改
在类定义之后，可以通过类名动态添加类数据属性，新增的类属性也被类和所有实例共有
实例数据属性只能通过实例访问
在实例生成后，还可以动态添加实例数据属性，但是这些实例数据属性只属于该实例
注意：
在类定义的方法中调用类数据属性时，要用引用的方式，如：Student.skills
虽然通过实例可以访问类属性，但是，不建议这么做，最好还是通过类名来访问类属性，从而避免属性隐藏带来的不必要麻烦。
End of explanation
class Student(object):
    Student calss
    skills = []
    def __init__(self, name):
        self.name = name
stu = Student('ly')
print Student.__name__    # 类名：Student
print Student.__doc__       # 类的说明文档
print Student.__bases__
print Student.__class__     # 类的__class__
print stu.__class__             # 实例对象的__class__
print isinstance(stu, Student)
print dir(Student)
print dir(stu)
print Student.__name__    # 通过类Student能调用__name__
print stu.__name__            # 但是通过实例对象不能调用__name__
Explanation: 特殊的类属性
|类属性    |    含义    |
|:------        |:-------------|
|_name_|    类的名字（字符串）|
|_doc_  |类的文档     |
|_bases_    |类的所有父类组成的元组 |
|_dict_ |类的属性组成的字典 |
|_module_   |类所属的模块 |
|_class_    |类对象的类型 |
End of explanation
class Animal(object):
    # 初始化方法
    def __init__(self, name):
        self.name = name
    
    # 普通实例方法
    def get_name(self):
        return self.name
        
animal = Animal(name='ly')
print animal.name
print animal.get_name()
Explanation: 方法
实例方法
静态方法
类方法
实例方法
如果希望类里的一个函数能作为该类实例的方法，这个函数至少需要有一个表示其调用对象的形参，放在函数定义参数表的第一个位置，通常取名self（可以用任何名字，这只是Python社区的习惯）。
初始化方法是一种特殊的实例方法。
作用：新建一个实例对象时，自动调用初始化方法，给实例对象绑定一些属性。
End of explanation
class Animal(object):
    @staticmethod
    def hello():
        print 'hello'
        
animal = Animal()
Animal.hello()    # 类调用
animal.hello()    # 实例对象调用
Explanation: 定义一个Animal类，初始化方法把形参name赋值给实例对象数据属性name
通过animal.get_name()调用实例方法，实例对象animal作为get_name的第一个实参约束到函数的第一个形参self，所以在实例方法定义中对self的操作都是对调用这个实例方法的实例的操作。
总结：实例方法能够对实例对象操作，在定义时至少有一个形参，其中第一个形参通常是self，当实例对象调用方法时，这个对象就被约束到self上（初始化时也类似）。
@staticmethod 静态方法
静态方法就是在类里面定义的普通函数，但根据信息局部化的原则，局部使用的功能不应该定义为全局函数，所以把它定义在类内部。
静态方法的参数表 不应该有 self 参数，在其他方面也没有任何限制.
它不会对类的实例进行操作，但类和类的实例都可以调用静态方法，可以从其定义所在类的名字出发通过圆点形式调用，也可以从该类的对象（实例）通过圆点形式调用。
End of explanation
class Countable(object):
    counter = 0
    def __init__(self):
        Countable.counter += 1    # 在方法中调用类数据属性要用引用的方式
        
    @classmethod
    def get_count(cls):
        return Countable.counter
a = Countable()
b = Countable()
print Countable.get_count()    # 类调用
print a.get_count()                   # 实例对象调用
Explanation: @classmethod 类方法
类方法和实例方法一样，都有参数限制，在定义类方法时必须有一个表示其调用类的参数，习惯用 cls 作为参数名，通常用类方法实现与本类所有对象有关的操作。类和实例对象都能调用类方法。
End of explanation
class Animal(object):
    def __init__(self, name, age):
        self.__name = name
        self.age = age
    
animal = Animal('ly', 25)
print animal.age
print animal._Animal__name
print animal.name
Explanation: 私有变量
官方教程：
"Private" instance variables that cannot be accessed except from inside an object don’t exist in Python, However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice. 
在内部，python使用一种name mangling 技术，将 __membername替换成 _classname__membername，所以你在外部使用原来的私有成员的名字时，会提示找不到，可以通过这种方式访问私有变量，但是强烈不建议，因为不同版本的Python解释器可能会改成不同的名字。
End of explanation
class Animal(object):
    def __init__(self, name, age):
        self.__name = name
        self.__age = age
        
    def get_age(self):
        return self.__age
    
    def modified_age(self, age):
        if age > 0 and age < 120:    # 参数检查
            self.__age = age
animal = Animal('ly', 25)
print  animal.get_age()
animal.modified_age(26)
print  animal.get_age()
Explanation: 通常在类中定义方法去访问和修改这些私有变量。
数据封装，确保了外部代码不能随意修改对象内部的状态，通过访问限制的保护，代码更加健壮。
通过定义的方法修改参数，可以对参数做检查，同样使代码健壮。
End of explanation
class Mystr(str):    # 继承自str
    pass
s = Mystr(123)
print issubclass(Mystr, str)
print isinstance(s, str), isinstance(s, Mystr)
Explanation: 约定把以一个下划线开头的名字做为实例对象内部的东西，永远不从对象的外部访问他们
两个下划线开头（不是以两个下划线结尾），在类之外采用属性访问方式直接写这个名字将无法找到他
注意：以两个下划线开头和结尾的是特殊变量（如：_doc_），特殊变量是可以直接访问的。
继承
基于类和对象的程序设计成为面向对象的程序设计（OOP）
定义类
创建实例对象
调用对象的方法完成计算工作，包括对象间的信息交换
基类 派生类
替换原理：一个类的实例对象的上下文可以使用其派生类的实例对象
Python内置函数issubclass检查两个类是否有继承关系
End of explanation
class Parent(object):
    '''
    parent class
    '''
    numList = []
    def numAdd(self, a, b):
        return a+b
 
class Child(Parent):
    pass
parent = Parent()
child = Child()
print Parent.__doc__
print Child.__doc__    # 子类无法继承__doc__
print Child.__bases__
print Parent.__bases__
print Parent.__class__    # 类型
print Child.__class__
print parent.__class__
print child.__class__
Explanation: 注意：
说明文档对于类，函数/方法，以及模块来说是唯一的，也就是说__doc__属性是不能从父类中继承来的。
End of explanation
class Parent(object):
    def f(self):
        self.g()
    
    def g(self):
        print 'Parent.f.g'
        
class Child(Parent):
    def g(self):
        print 'Child.f.g'
        
child = Child()
child.f()
Explanation: 方法查找
一个实例对象调用方法，Python解释器需要确定调用的函数（在哪个类里定义的函数），这个过程沿着继承关系进行。 
有一点需要注意：
动态约束
静态约束
在程序设计领域，通过动态约束确定调用关系的函数称为虚函数
End of explanation
class Root(object):
    def __init__(self):
        print("this is Root")
class B(Root):
    def __init__(self):
        print("enter B")
        super(B, self).__init__()
        print("leave B")
class C(Root):
    def __init__(self):
        print("enter C")
        super(C, self).__init__()
        print("leave C")
class D(B, C):
    pass
d = D()
print(d.__class__.__mro__)
print D.__mro__
print D.mro()
Explanation: 标准函数 super()
不要一说到 super 就想到父类！super 指的是 MRO 中的下一个类！
MRO: Method Resolution Order, 方法解析顺序，代表类继承顺序
python
def super(cls, inst):
    mro = inst.__class__.mro() # Always the most derived class
    return mro[mro.index(cls) + 1]
super()的作用：
1. 通过inst返回所属类的mro
2. 通过cls定位当前mro中的index，并返回mro中的下一个
End of explanation
class Parent(object):
    __slots__ = ('name')          # __slots__
    def __init__(self, name):
        self.name = name
        
a = Parent('ly')
print a.name
Parent.age = 25    # slots对通过类名动态添加属性没有限制
print a.age
Explanation: 首先建立一个实例对象，会自动调用初始化方法，为什么 B 的 init 会被调用：因为 D 没有定义 init，所以会在 MRO 中找下一个类，去查看它有没有定义 init，也就是去调用 B 的 init。
在 MRO 中，基类永远出现在派生类后面，如果有多个基类，基类的相对顺序保持不变
上面的例子的继承链（MRO顺序）：[D, B, C, Root, Object]
_slots_
当我们通过一个类创建了实例之后，仍然可以给实例动态添加属性，但是这些属性只属于这个实例。
有些时候，我们可以需要限制类实例对象的属性，这时就要用到类中的__slots__属性了。__slots__属性对于一个tuple，只有这个tuple中出现的属性可以被类实例使用。
使用__slots__要注意，__slots__定义的属性仅对当前类的实例起作用，对继承的子类实例是不起作用的
如果子类本身也有_slots__属性，子类的属性就是自身的__slots__加上父类的__slots_
实例不超过万级别的类，__slots__是不太值得使用的。
End of explanation
try:
    a = 5 / 0
    
except ZeroDivisionError:
    print 'error'
    
finally:
    print 'end'
Explanation: _new_
编程实践
通常把类的定义写在模块最外层，这样定义的类在整个模块（.py文件）都能使用，而且允许其他模块通过 import 语句导入和使用
Python 异常
Python 的异常都是类（class），运行时产生异常就是生成相应类的实例对象，异常处理机制完全基于面向对象的概念和性质。
所有异常类的基类 BaseException，其最主要的子类是 Exception，内置异常类都是从这个类直接或间接派生。
捕捉异常语句：try: ... except ... finally:...
End of explanation
<END_TASK>