### 7.1.1 面向过程观点
我们用一个简单程序来说明传统程序设计的思维方式。
【程序 7.1】eg7_1.py
```
x = 1
y = 2
z = x + y
print z
```
到目前为止,我们在编程时基本上都是这样思考的:先用特定数据类型的常量或变量来 表示数据(如程序 7.1 中分别存入变量 x 和 y 的整数类型值 1 和 2),然后再利用合适的操作(如程序 7.1 中的加法运算“+”)按一定的步骤来处理数据。在这种思考方式下,数据和对 数据的操作被看作是分离的两件事情:数据只是信息的表示,不表达任何操作,在程序中处 于“被动”地位;而对数据的操作在程序中则处于“主动”地位,是驱动程序实现特定功能 的力量。程序 7.1 可视为用操作“+”主动地去处理被动的数据 x 和 y,从而实现加法功能。 图 7.1 以一个比喻来形象地展示这种观点:数据与操作之间的关系正如心与箭的关系——没 有丘比特的箭,两颗心是不会彼此连结的。
![](https://box.kancloud.cn/2016-02-22_56cafce3615bb.png)
图 7.1 传统观点:数据与操作分离
在数据与操作分离的传统观点下,通常以算法过程的设计为主线来展开程序设计,故可称为以过程为中心的程序设计。以求解一元二次方程的程序 3.6 为例,数据(系数 a、b、c) 明确后,需要精心设计的是处理这些数据的操作过程:先计算判别式 b2-4ac,然后根据判别 式的值判断方程是否有解,有解的情况下再利用公式求解,最后输出结果。
在以操作为中心的设计理念下,程序中的数据有时对整个操作过程都是公开的,可以被 操作过程中的每个步骤访问、处理。例如,假设程序 7.1 的操作不是单一的加法,而是在加法操作(第 3 行)之后还有两个操作:
```
w = x – y
z = z * w
```
可以看出,数据(x、y、z、w)对程序中所有的操作都是公开的。这时,程序中对数据的访问不受任何控制,非常容易出现错误的操作。
当然,实际的应用程序不会像程序 7.1 这样简单。复杂程序中不但数据复杂,而且对数 据的操作也非常复杂,所有操作可能形成漫长而曲折的过程。为了应付操作过程的复杂性, 按照第 4 章所介绍的模块化编程思想,可以将复杂操作过程组织成为若干个较小的模块—— 函数,每个函数实现一个相对简单的、单一的功能。例如下面这个“复杂”程序①:
【程序 7.2】eg7_2.py
```
def op1(a,b):
return a * a - b * b
def op2(a,b):
return a ** b + b ** a
x = 1
y = 2
z = 3
result1 = op1(x,y)
result2 = op2(x,z)
print result1 + result2
```
从一个更抽象的层次看,每个函数其实相当于一个操作。与程序 7.1 相比,程序 7.2 对 更多的数据(x、y、z)进行更复杂的操作:先执行 op1 操作,再执行 op2 操作,最后输出结 果。无论是程序 7.1 的简单操作“+”还是程序 7.2 的复杂操作“op1”、“op2”,它们都是“对 数据的操作”,仍然属于“数据与操作相互分离”的思考方式,整个程序仍然是对数据按一定 顺序执行操作的过程。
不过,作为高抽象级别操作的函数具有一定的访问控制能力。函数就像一个提供某种功 能的黑箱,使用者需要的只是它的功能,并不需要知晓它内部是如何实现功能的。函数内部 处理的数据不是对整个程序都公开的数据,一个函数不能访问另一个函数内部的数据。然而, 程序中仍然有一些全局数据是对所有操作(包括函数)公开的,仍然存在前述访问控制问题, 例如程序 7.2 中的两个函数 op1 和 op2 都在处理数据 x。
总之,不管程序是简单还是复杂,不管操作是语句级的还是函数级的,传统程序设计都 是按照数据与操作分离的观点,以过程为中心展开程序设计的。在这种面向过程的编程范型 中,强调的是对数据的操作过程,程序员思考的主要问题是数据如何表示、对各数据执行什 么操作以及各操作的先后顺序如何安排。当程序很复杂时,可以采用自顶向下设计和模块化 设计方法,将使用低级别操作的复杂过程设计成使用高级别操作的简单过程。
要指出的是,基于数据与操作分离观点的面向过程编程具有其内在的局限性,在处理某 些复杂问题和系统时显得不合适。例如,图形用户界面(GUI)程序②就不属于“对给定数据,
> ① 这个程序自然一点也不复杂,但不妨碍它可以用于说明复杂操作的问题。
> ② 详见第 8 章。
按特定次序对数据进行操作,操作完毕程序即告结束”的程序执行模式。以 Word 程序为例, 当启动 Word 打开文档(即程序数据)之后,接下去对数据如何操作呢?Word 程序并不知道 该做什么,它只能等在那里。接下去用户可能用键盘输入文本,也可能用鼠标点击菜单或工 具栏进行存盘或打印,总之用户需要通过某种交互事件来告诉 Word 程序该如何操作数据, 一个操作完成后 Word 又进入等待状态。可见,GUI 程序属于“先建立一个图形界面,然后 等待来自用户的不可预知的事件发生;事件发生后才导致执行某些操作,事件处理完毕又回 到等待状态”这样一种程序执行模式,程序从启动到结束的具体执行过程取决于事件发生的 顺序,不像传统程序那样预定义了执行顺序。
为了适应 GUI 程序这类没有明确的预定义操作次序、靠不确定的事件来驱动的程序和系 统的开发,提高开发效率和质量,计算机科学家提出了一种新的观点来看待数据与操作之间 的关系,即面向对象的观点。
- 前言
- 第 1 章 计算与计算思维
- 1.1 什么是计算?
- 1.1.1 计算机与计算
- 1.1.2 计算机语言
- 1.1.3 算法
- 1.1.4 实现
- 1.2 什么是计算思维?
- 1.2.1 计算思维的基本原则
- 1.2.2 计算思维的具体例子
- 1.2.3 日常生活中的计算思维
- 1.2.4 计算思维对其他学科的影响
- 1.3 初识 Python
- 1.3.1 Python 简介
- 1.3.2 第一个程序
- 1.3.3 程序的执行方式
- 1.3.4 Python 语言的基本成分
- 1.4 程序排错
- 1.5 练习
- 第 2 章 用数据表示现实世界
- 2.1 数据和数据类型
- 2.1.1 数据是对现实的抽象
- 2.1.1 常量与变量
- 2.1.2 数据类型
- 2.1.3 Python 的动态类型*
- 2.2 数值类型
- 2.2.1 整数类型 int
- 2.2.2 长整数类型 long
- 2.2.3 浮点数类型 float
- 2.2.4 数学库模块 math
- 2.2.5 复数类型 complex*
- 2.3 字符串类型 str
- 2.3.1 字符串类型的字面值形式
- 2.3.2 字符串类型的操作
- 2.3.3 字符的机内表示
- 2.3.4 字符串类型与其他类型的转换
- 2.3.5 字符串库 string
- 2.4 布尔类型 bool
- 2.4.1 关系运算
- 2.4.2 逻辑运算
- 2.4.3 布尔代数运算定律*
- 2.4.4 Python 中真假的表示与计算*
- 2.5 列表和元组类型
- 2.5.1 列表类型 list
- 2.5.2 元组类型 tuple
- 2.6 数据的输入和输出
- 2.6.1 数据的输入
- 2.6.2 数据的输出
- 2.6.3 格式化输出
- 2.7 编程案例:查找问题
- 2.8 练习
- 第 3 章 数据处理的流程控制
- 3.1 顺序控制结构
- 3.2 分支控制结构
- 3.2.1 单分支结构
- 3.2.2 两路分支结构
- 3.2.3 多路分支结构
- 3.3 异常处理
- 3.3.1 传统的错误检测方法
- 3.3.2 传统错误检测方法的缺点
- 3.3.3 异常处理机制
- 3.4 循环控制结构
- 3.4.1 for 循环
- 3.4.2 while 循环
- 3.4.3 循环的非正常中断
- 3.4.4 嵌套循环
- 3.5 结构化程序设计
- 3.5.1 程序开发过程
- 3.5.2 结构化程序设计的基本内容
- 3.6 编程案例:如何求 n 个数据的最大值?
- 3.6.1 几种解题策略
- 3.6.2 经验总结
- 3.7 Python 布尔表达式用作控制结构*
- 3.8 练习
- 第 4 章 模块化编程
- 4.1 模块化编程基本概念
- 4.1.1 模块化设计概述
- 4.1.2 模块化编程
- 4.1.3 编程语言对模块化编程的支持
- 4.2 Python 语言中的函数
- 4.2.1 用函数减少重复代码 首先看一个简单的用字符画一棵树的程序:
- 4.2.2 用函数改善程序结构
- 4.2.3 用函数增强程序的通用性
- 4.2.4 小结:函数的定义与调用
- 4.2.5 变量的作用域
- 4.2.6 函数的返回值
- 4.3 自顶向下设计
- 4.3.1 顶层设计
- 4.3.2 第二层设计
- 4.3.3 第三层设计
- 4.3.4 第四层设计
- 4.3.5 自底向上实现与单元测试
- 4.3.6 开发过程小结
- 4.4 Python 模块*
- 4.4.1 模块的创建和使用
- 4.4.2 Python 程序架构
- 4.4.3 标准库模块
- 4.4.4 模块的有条件执行
- 4.5 练习
- 第 5 章 图形编程
- 5.1 概述
- 5.1.1 计算可视化
- 5.1.2 图形是复杂数据
- 5.1.3 用对象表示复杂数据
- 5.2 Tkinter 图形编程
- 5.2.1 导入模块及创建根窗口
- 5.2.2 创建画布
- 5.2.3 在画布上绘图
- 5.2.4 图形的事件处理
- 5.3 编程案例
- 5.3.1 统计图表
- 5.3.2 计算机动画
- 5.4 软件的层次化设计:一个案例
- 5.4.1 层次化体系结构
- 5.4.2 案例:图形库 graphics
- 5.4.3 graphics 与面向对象
- 5.5 练习
- 第 6 章 大量数据的表示和处理
- 6.1 概述
- 6.2 有序的数据集合体
- 6.2.1 字符串
- 6.2.2 列表
- 6.2.3 元组
- 6.3 无序的数据集合体
- 6.3.1 集合
- 6.3.2 字典
- 6.4 文件
- 6.4.1 文件的基本概念
- 6.4.2 文件操作
- 6.4.3 编程案例:文本文件分析
- 6.4.4 缓冲
- 6.4.5 二进制文件与随机存取*
- 6.5 几种高级数据结构*
- 6.5.1 链表
- 6.5.2 堆栈
- 6.5.3 队列
- 6.6 练习
- 第 7 章 面向对象思想与编程
- 7.1 数据与操作:两种观点
- 7.1.1 面向过程观点
- 7.1.2 面向对象观点
- 7.1.3 类是类型概念的发展
- 7.2 面向对象编程
- 7.2.1 类的定义
- 7.2.2 对象的创建
- 7.2.3 对象方法的调用
- 7.2.4 编程实例:模拟炮弹飞行
- 7.2.5 类与模块化
- 7.2.6 对象的集合体
- 7.3 超类与子类*
- 7.3.1 继承
- 7.3.2 覆写
- 7.3.3 多态性
- 7.4 面向对象设计*
- 7.5 练习
- 第 8 章 图形用户界面
- 8.1 图形用户界面概述
- 8.1.1 程序的用户界面
- 8.1.2 图形界面的组成
- 8.1.3 事件驱动
- 8.2 GUI 编程
- 8.2.1 UI 编程概述
- 8.2.2 初识 Tkinter
- 8.2.3 常见 GUI 构件的用法
- 8.2.4 布局
- 8.2.5 对话框*
- 8.3 Tkinter 事件驱动编程
- 8.3.1 事件和事件对象
- 8.3.2 事件处理
- 8.4 模型-视图设计方法
- 8.4.1 将 GUI 应用程序封装成对象
- 8.4.2 模型与视图
- 8.4.3 编程案例:汇率换算器
- 8.5 练习
- 第 9 章 模拟与并发
- 9.1 模拟
- 9.1.1 计算机建模
- 9.1.2 随机问题的建模与模拟
- 9.1.3 编程案例:乒乓球比赛模拟
- 9.2 原型法
- 9.3 并行计算*
- 9.3.1 串行、并发与并行
- 9.3.2 进程与线程
- 9.3.3 多线程编程的应用
- 9.3.4 Python 多线程编程
- 9.3.5 小结
- 9.4 练习
- 第 10 章 算法设计和分析
- 10.1 枚举法
- 10.2 递归
- 10.3 分治法
- 10.4 贪心法
- 10.5 算法分析
- 10.5.1 算法复杂度
- 10.5.2 算法分析实例
- 10.6 不可计算的问题
- 10.7 练习
- 第 11 章 计算+X
- 11.1 计算数学
- 11.2 生物信息学
- 11.3 计算物理学
- 11.4 计算化学
- 11.5 计算经济学
- 11.6 练习
- 附录
- 1 Python 异常处理参考
- 2 Tkinter 画布方法
- 3 Tkinter 编程参考
- 3.1 构件属性值的设置
- 3.2 构件的标准属性
- 3.3 各种构件的属性
- 3.4 对话框
- 3.5 事件
- 参考文献