一、抽象数据类型初识

定义一个抽象数据类型(ADT),目的是要定义一类计算对象,它们具有某些特定的功能。(抽象数据类型可以自定义)

在建立这种抽象时,人们不希望暴露其实现的内部细节。对更复杂的抽象,信息隐藏的意义可能更重要。

python的内置数据类型(也是一种抽象数据类型):

  逻辑类型bool、数值类型int和float等、字符串类型str、组合数据类型  

python中抽象数据类型分为:

  • 不变数据类型:str、tuple、frozenset(不可变集合)

            只能构造新对象或者取得已有对象的特性,不能修改已建立的对象。

  • 可变数据类型:list、dict、set(可变集合)

ADT是一种思想,也是一种组织程序的技术。

那么如何在python里实现抽象数据类型呢?

二、Python的类

1. python中利用class定义(类定义)实现抽象数据类型。(就是我们所学习的面向对象)

实际上,python语言把内置数据类型都看作类。str、int、list、dict、tuple、set、frozenset都是类。

class Rational:
    def __init__(self,num,den=1):   # __init__为初始化方法,其余为实例方法
        self.num = num
        self.den = den
    def plus(self,another):
        den = self.den * another.den
        num = (self.num * another.den + self.den * another.num)
        return Rational(num,den)
    def print(self):
        print(str(self.num) + '/' + str(self.den))
r1 = Rational(3,5)
r2 = r1.plus(Rational(7,15))   # r2也是一个对象
r2.print()

 

  由于隐藏抽象的内部信息在软件领域意义重大,有些编程语言为此提供了专门机制。python语言没有专门服务于这种需求的机制,只能依靠一些编程约定。即封装

(1)__属性名(函数名)表示私有,不应该在类之外使用。

(2)静态方法:@staticmethod

  • 静态方法的参数表中不应该有self参数;
  • 可以从其定义所在类的名字出发通过圆点形式调用,也可以从该类的对象出发通过圆点形式调用;
  • 本质上说,静态方法就是在类里面定义的普通函数,但也是该类的局部函数 

 来看个例子:有理数类

class Rational:
    def __init__(self,num,den):
        self.num = num    # 分子
        self.den = den    # 分母

    # 两个有理数相加
    def plus(self,another):
        den = self.den * another.den
        num = self.num * another.den + self.den * another.num
        return Rational(num ,den)

    def print(self):
        print(str(self.num)+'/'+str(self.den))
r = Rational(1,10)
r2 = Rational(2,10)
R = r.plus(r2)
print(r.plus(r2))            #  <__main__.Rational object at 0x00B023F0>
R.print()                    # 30/100         没有化简

还有两个问题需要考虑,

  1. 有理数的化简问题,避免造成无意义的资源浪费;
  2. 有理数类的初始化方法没有检查参数,既没有检查参数的类型是否合适(显然,两个参数都应该是整数),也没有检查分母是否为0。此外,人们传送给初始化方法的实参可能有正有负,内部表示应该标准化,例如,保证所有有理数内部的分母为正,用分子的正负表示有理数的正负。这些检查和变化都应该在有理数的初始化方法里完成,保证构造出的有理数都是合理合规的对象。