伯克利CS 61A的教学用书笔记和一些课程笔记

The general technique of isolating the parts of a program that deal with how data are represented from the parts that deal with how data are manipulated is a powerful design methodology called data abstraction. Data abstraction makes programs much easier to design, maintain, and modify. 将数据的表示和数据的操作分离开的一种抽象方法,称为数据抽象。

它将如何使用复合数据与如何构造复合数据隔离开,尽可能地满足通用性,

2.2.1   Example: Rational Numbers

有理数都可以表示成分数的形式:<numerator>/<denominator>。<numerator> 和 <denominator>都是整数。

对于浮点数,很多时候会出现误差,不能直接进行相等判断等操作,比如

>>> 1/3
0.3333333333333333
>>> 1/3 == 0.333333333333333300000  # Dividing integers yields an approximation
True

所以可以考虑用分数来精确表示。下面进行数据抽象。

有理数的值就是由分子和分母决定的,先假设我们已经有方法将一个有理数构造为分子和分母两部分,也有方法获取一个有理数的分子或者分母:

  • rational(n, d) 基于n和d返回有理数
  • numer(x) 返回有理数x的分子
  • denom(x) 返回有理数x的分母

We are using here a powerful strategy for designing programs: wishful thinking. 一种设计程序的强有力的策略:wishful thinking。先不考虑以上三个函数是怎么实现的,甚至不考虑有理数具体通过程序应该怎么表示。

我们先考虑有理数的操作,加法、乘法、打印、相等判断:

>>> def add_rationals(x, y):nx, dx = numer(x), denom(x)ny, dy = numer(y), denom(y)return rational(nx * dy + ny * dx, dx * dy)>>> def mul_rationals(x, y):return rational(numer(x) * numer(y), denom(x) * denom(y))>>> def print_rational(x):print(numer(x), '/', denom(x))>>> def rationals_are_equal(x, y):return numer(x) * denom(y) == numer(y) * denom(x)

现在我们基于rational,numer,denom三个函数,实现了对有理数的处理,接下来就是实现这三个函数,进一步思考,我们需要的是将分子和分母整合成为一个复合值的方法。

2.2.2   Pairs

python提供了一种叫列表的复合结构,可以用来形成复合对。

>>> pair = [10, 20]
>>> pair
[10, 20]
>>> x, y = pair
>>> x
10
>>> y
20
>>> pair[0]
10
>>> pair[1]
20
>>> from operator import getitem
>>> getitem(pair, 0)
10
>>> getitem(pair, 1)
20

两元素列表不是python中表示pairs的唯一方式,利用列表,我们就可以将分子和分母整合到一起,用来表示有理数。

>>> def rational(n, d):return [n, d]
>>> def numer(x):return x[0]
>>> def denom(x):return x[1]

现在,我们就可以进行计算了。

>>> half = rational(1, 2)
>>> print_rational(half)
1 / 2
>>> third = rational(1, 3)
>>> print_rational(mul_rationals(half, third))
1 / 6
>>> print_rational(add_rationals(third, third))
6 / 9

但是我们的方法仍然有缺陷,比如最后的6/9并没有化到最简。我们还需要将分子分母除以他们的最大公约数。

python库的gcd函数能求出两个数的最大公约数。

>>> from fractions import gcd
>>> def rational(n, d):g = gcd(n, d)return (n//g, d//g)

然后,我们完成了对有理数的抽象。我们只改变了构造有理数的函数,而不需要改动处理有理数的函数。

>>> print_rational(add_rationals(third, third))
2 / 3

2.2.3   Abstraction Barriers

抽象壁垒。我们在上面的例子中可以看到,我们对数据的构造表示与数据的处理进行了隔离,我们操作数据时不需要关心数据是怎么构造的,就像我们操作list的时候不关心list在python中具体是怎么实现的一样。

Parts of the program that... Treat rationals as... Using only...
Use rational numbers to perform computation whole data values add_rational, mul_rational, rationals_are_equal, print_rational
Create rationals or implement rational operations numerators and denominators rational, numer, denom
Implement selectors and constructor for rationals two-element lists list literals and element selection

如上表,我们有三层隔离,第一层,我们只关心怎么用有理数,将有理数当作一个整体,而不关心有理数具体是怎么构造的,第二层,我们只关心有理数具体是构造的,将有理数视为分子和分母,我们怎么用这样的构造方法来实现对有理数的操作,第三层,我么只关心怎么使用list来构造有理数,不关心python的list是怎么具体实现的。在上面的每一层中,最后一列中的函数执行一个抽象屏障。这些函数由较高层调用,并使用较低层抽象实现。

An abstraction barrier violation occurs whenever a part of the program that can use a higher level function instead uses a function in a lower level. 壁垒冲突

比如,要实现计算有理数x的平方,最好使用已经实现了的mul_rational函数,因为这样就不涉及任何有理数的实现细节,也不会对有理数的构造带来更多假设。

>>> def square_rational(x):return mul_rational(x, x)

再比如,直接引用有理数的分子分母也会打破一个抽象隔离。

>>> def square_rational_violating_once(x):return rational(numer(x) * numer(x), denom(x) * denom(x))

再比如,直接用list实现,更会造成两次对抽象隔离的打破。

>>> def square_rational_violating_twice(x):return [x[0] * x[0], x[1] * x[1]]

抽象隔离使得程序更容易维护和修改,因为当程序依赖的特定表示的函数越少,那么想要更改该表示时需要的变动就越少,函数抽象程度、通用程度越高,越容易维护,上面三个例子对有理数x平方的实现,运行结果都是对的,但是只有第一个的实现对未来来说是健壮的,比如,numer和denom的函数名改变时,那么第二个函数也需要更改,而第一个函数不需要,如果对有理数的构造改变时,第三个函数就有可能需要更改,而第一个可以通过适当的编写方式而不用更改。

2.2.4   The Properties of Data

In general, we can express abstract data using a collection of selectors and constructors, together with some behavior conditions. As long as the behavior conditions are met (such as the division property above), the selectors and constructors constitute a valid representation of a kind of data. The implementation details below an abstraction barrier may change, but if the behavior does not, then the data abstraction remains valid, and any program written using this data abstraction will remain correct. 由于抽象隔离的存在,当用来表示抽象数据的表达方式、行为条件没有改变时,抽象数据的实现细节就算改变了,这个数据抽象往往仍然是有效的,而任何使用这种抽象数据的程序都是正确的。比如对于将两个整数构造为一个有理数的函数rational(n, d),是以list为基础实现的,但是就算不是用list,是用其他可以将n,d整合的数据类型,也同样可以实现,整个程序的其他地方也不需要改变,前文也提到list并不是实现rational的唯一方式。

下面我们不用list,自己实现一个将整数整合为一个有理数的函数。

  • 要求pair输入为两个整数pair(x, y),而且 select(p, 0) 返回x,而且 select(p, 1) 返回y
>>> def pair(x, y):"""Return a function that represents a pair."""def get(index):if index == 0:return xelif index == 1:return yreturn get>>> def select(p, i):"""Return the element at index i of pair p."""return p(i)>>> p = pair(20, 14)
>>> select(p, 0)
20
>>> select(p, 1)
14

虽然这些高阶函数(higher-order function)完全不符合我们对有理数的直观概念,但是它是足以表示有理数,我们实现这个例子并不是说python实际上就是这么做的,而是说我们可以这么做,不依靠list,我们可以用很多方式实现对有理数的构造。

所以,对数据的抽象可以让我们轻松的在实现之间切换。

Composing Programs 2.2 Data Abstraction相关推荐

  1. CS61A fa2021 Composing Programs 2.7 Object Abstraction 对象抽象

    原文 2.7   对象抽象(Object Abstraction) 面向对象为我们提供了多种数据抽象形式.各种抽象形式之间严密的逻辑层级使得我们在建立与使用时,不用担心他们之间会发生冲突. 对象抽象中 ...

  2. 《Composing Programs》学习笔记(0)目录(关键词:软件工程)

    Welcome to Composing Programs, a free online introduction to programming and computer science. 欢迎来到& ...

  3. 关于书籍“Composing Programs”1.6.3自定义函数的嵌套定义与非嵌套定义的比较

    最近开始刷ucb的cs61-2018年课程,配套书籍是John DeNero的"Composing Programs".书中1.6.3部分讲到user defined functi ...

  4. 【AP_EJOR】Robust solutions to multi-objective linear programs with uncertain data(1)

    Navigator Paper Link Introduction main contributions Preliminaries Paper Link Robust solutions to mu ...

  5. 《Composing Programs》学习笔记(1.1)开始(关键词:软件工程/抽象/函数)

    Chapter 1: Building Abstractions(抽象) with Functions 1.1 Getting Started 第1章:利用函数构造抽象 1.1 开始 Computer ...

  6. Composing Programs 2.3 Sequence - 02

    伯克利CS 61A的教学用书笔记和一些课程笔记 一些python笔记 01 关于sum >>> sum([2, 3, 4]) 9 >>> sum([2, 3, 4] ...

  7. CS61A fa2021 Composing Programs 2.8 Efficiency 效率

    如何抽象和处理数据,答案往往不是唯一的.我们倾向于在众多答案中选择最有效率的一个.效率取决于我们抽象今和处理数据所使用的计算机资源,例如完成一个函数计算或者声明一个实例需要花多少时间,多少内存等.在代 ...

  8. 算法第四版习题解答(1.2 Data Abstraction)

    前言 使用的是<算法>第四版英文版,主要是习题解答. 书中jar包的导入请戳:算法(第四版)中algs4.jar下载和使用 EXERCISES 1.2.1 import edu.princ ...

  9. 一个月学会Python的Quora指南和资料放送

    欢迎关注天下博客:http://blog.genesino.com/2017/12/python-quora/ 如何一个月学会使用Python 文章翻译自Quora上的回帖,略有改动.原文链接:htt ...

  10. SICP:Building Abstractions with Data

    为什么80%的码农都做不了架构师?>>>    2.1 Introduction to Data Abstraction our programs should use data i ...

最新文章

  1. IROS2020 | 面向城市自动驾驶应用的概率语义建图
  2. 网站SEO优化中导航对用户体验的重要性
  3. 在python面向对象编程中、属性分为_Python-面向对象编程(1.概述)
  4. mysql DATETIME和TIMESTAMP类型
  5. android webview url scheme,Android Webview ERR_UNKNOWN_URL_SCHEME错误
  6. 安卓手机可以改鸿蒙吗,华为鸿蒙2.0可以替代安卓吗,华为鸿蒙2.0优势在哪
  7. Integer与int的区别
  8. 传爱立信两大股东欲弹劾CEO卫翰思 股价应声反弹
  9. android 网页取词,有道词典屏幕取词怎么用?,你知道吗?在浏览网页
  10. win10自动停用打印服务器,win10系统添加打印机总是自动关闭打印服务的技巧介绍...
  11. linux锐捷代码_Linux下锐捷上网操作
  12. 图像入门:MATLAB图像识别
  13. RT-Thread : STM32 系列外设驱动添加指南
  14. win7蓝牙热点自动断开
  15. Win7电脑定时关机
  16. ThrottleStop CPU频率调节
  17. ES 之 Routing
  18. 最新Exsi-6.7.0U3b版本下载
  19. 计算机网络 第二讲:HTTP
  20. 3.灰色预测模型(Gray Forecast Model)

热门文章

  1. lammps复杂形状建模案例——胶囊粒子分子模型
  2. unity 3d实例:创建游戏对象、旋转的立方体、Unity3D Button、图片按钮、Box控件、Label控件、Background Color、Color
  3. Xcode 秘籍 —— 很多 iOS 开发者都不知道的基本操作
  4. hp服务器改系统启动项,hp笔记本如何进入bios修改启动项
  5. 双机串行通讯实验c语言编程,51单片机编程:教你实现双机串行通信功能
  6. 从零开始学习股票知识
  7. 从投入产出简析直复营销
  8. GMM-HMM语音识别
  9. 判断某个字符串是否为数字
  10. 服务器Ubuntu 16.04 更新NVIDIA显卡驱动-命令行版本及报错完美解决