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