跳到主要内容

进阶程序设计

A-Level 计算机科学 · 第 20 主题

训练
讲义 词汇表
20.1

编程范式

大纲
Candidates should be able to: Notes and guidance
Understanding what is meant by a programming paradigm
Show understanding of the characteristics of a number of programming paradigms:
Low-level Low-level Programming: • understanding of and ability to write low-level code that uses various addressing modes: immediate, direct, indirect, indexed and relative
Imperative (Procedural) Imperative (Procedural) programming: • Assumed knowledge and understanding of Structural Programming (see details in AS content section 11.3) • understanding of and ability to write imperative (procedural) programming code that uses variables, constructs, procedures and functions. See details in AS content
Object Oriented Object-Oriented Programming (OOP): • understanding of the terminology associated with OOP (including objects, properties/attributes, methods, classes, inheritance, polymorphism, containment (aggregation), encapsulation, getters, setters, instances) • understanding of how to solve a problem by designing appropriate classes • understanding of and ability to write code that demonstrates the use of OOP
Declarative Declarative programming: • understanding of and ability to solve a problem by writing appropriate facts and rules based on supplied information • understanding of and ability to write code that can satisfy a goal using facts and rules

来源:剑桥国际大纲

一个编程范式(programming paradigm)是一种编程风格——一种构造程序的方式,有它自己的思想和语言特性。本考纲里有四个编程范式

四个范式:低级、命令式、面向对象和声明式
四个范式:低级、命令式、面向对象和声明式

Low-level programming

贴近硬件地用机器码(machine code)或汇编语言(assembly language)编程,那里每条指令映射到 CPU 运行的东西。它给出对寄存器(registers)和内存地址(memory addresses)的直接访问,用不同的寻址方式(addressing modes,立即、直接、间接、变址和相对)。它非常快而紧凑,但特定于架构、繁琐,且难以维护。这是低级(low-level)编程,用于设备驱动、固件和引导加载程序。

Imperative (procedural) programming

命令式编程(imperative programming)中,程序员写一个改变程序状态的命令序列——赋值、条件、循环、函数调用。变量(variables)容纳状态;语句改变它;代码被组织成过程和函数(也叫结构化编程)。这是主题 9 和 11 的风格(Python、C)。当算法有清晰的顺序步骤时很强。

Object-oriented programming (OOP)

面向对象编程(object-oriented programming)中,程序从对象(objects)构建——把数据(属性(attributes))和操作(方法(methods))结合的单元。对象是(classes)的实例(instances)。四大支柱:

  • 封装(encapsulation)——一个对象的数据被隐藏在它的方法之后;外部代码只用公共方法,而不直接用数据。这保护对象并让它的内部改变而不弄坏调用者。例如,一个 BankAccount 隐藏它的 balance;你只通过 deposit()withdraw() 改变它,它们能强制执行一条规则如"永不低于零"。
  • 继承(inheritance)——一个子类(subclass)特化一个父类(superclass),继承它的属性和方法并添加或重写(overriding)它们。为"是一个"("一个 Manager 是一个 Employee")建模。
  • 多态(polymorphism)——不同的对象对同一个方法调用做出不同的响应;调用者不必知道确切的类型。每个 ShapeArea(),而一个 Circle 和一个 Rectangle 各以它们自己的方式实现它。
  • 抽象(abstraction)——显示一个简单的接口并隐藏实现。

其他术语:

  • 一个构造函数(constructor)是一个在对象被创建时运行的特殊方法,用来设置它的属性。
  • gettersetter 通过方法读写一个对象的属性(它的性质)。
  • 聚合(aggregation)和包含(containment)从其他对象构建一个对象(一个"有一个"关系)。

OOP 用于大型系统、GUI、模拟和游戏。

同一个调用 shape.Area() 为每个对象运行不同的代码:一个 Circle 计算 pi r 平方,一个 Rectangle 计算宽乘高
多态:同一个方法调用运行每个对象自己的代码
一个 Shape 的 UML 类图:一个三部分的框,带类名、私有属性(Name、Area、Perimeter,用减号标注)和公共方法(SetShape、calculateArea、calculatePerimeter,用加号标注)
一个 Shape 的类图:私有属性和公共方法
一个 UML 继承图:employee 父类在顶部,partTime 和 fullTime 子类在下面,每个用一个空心三角泛化箭头连到父类并添加它自己的属性和方法
继承:partTime 和 fullTime 是 employee 的子类
一个 BankAccount 对象,带一个只通过公共方法 deposit() 和 withdraw() 访问的私有 balance;外部代码不能直接碰数据
封装:一个对象的数据是私有的,只通过它的公共方法访问

Declarative programming

声明式编程(declarative programming)中,你说计算什么,而不是怎么——运行时算出步骤。两种:

  • 函数式编程(functional programming)——从纯函数(pure functions,无副作用(side effects);同样的输入总是给出同样的输出)组合而成。例子:Haskell、Lisp。
  • 逻辑编程(logic programming)——陈述事实和规则;引擎通过推理回答一个目标(goal,查询)。例子:Prolog。

一个熟悉的声明式例子是 SQL(结构化查询语言):SELECT * FROM Customer WHERE Country = 'UK' 说你想要什么,而不是怎么走过记录。

Comparing paradigms

范式 强项 典型语言
低级 最大控制、速度 assembly
命令式 直接、直观 C, Python
面向对象 模块化、为实体建模 Java, C#, Python
函数式 清晰、无副作用 Haskell, F#
逻辑 推理、规则 Prolog
数据库 数据查询 SQL

现代语言常常混合范式——Python 支持过程式、OOP 和函数式全部。正确的那个取决于问题。

探索

Programming concept lab

Connect examples to the programming idea they show.

词汇表 训练
英文 中文 拼音
programming paradigm 编程范式 biān chéng fàn shì
machine code 机器码 jī qì mǎ
assembly language 汇编语言 huì biān yǔ yán
registers 寄存器 jì cún qì
memory addresses 内存地址 nèi cún dì zhǐ
low-level 低级 dī jí
imperative programming 命令式编程 mìng lìng shì biān chéng
variables 变量 biàn liàng
object-oriented programming 面向对象编程 miàn xiàng duì xiàng biān chéng
objects 对象 duì xiàng
attributes 属性 shǔ xìng
methods 方法 fāng fǎ
instances 实例 shí lì
classes lèi
encapsulation 封装 fēng zhuāng
inheritance 继承 jì chéng
subclass 子类 zi lèi
superclass 父类 fù lèi
overriding 重写 zhòng xiě
polymorphism 多态 duō tài
abstraction 抽象 chōu xiàng
constructor 构造函数 gòu zào hán shù
declarative programming 声明式编程 shēng míng shì biān chéng
functional programming 函数式编程 hán shù shì biān chéng
pure functions 纯函数 chún hán shù
side effects 副作用 fù zuò yòng
logic programming 逻辑编程 luó jí biān chéng
SQL 结构化查询语言 jié gòu huà chá xún yǔ yán
addressing modes 寻址方式 xún zhǐ fāng shì
aggregation 聚合 jù hé
containment 包含 bāo hán
20.2

文件处理与异常处理

大纲
Candidates should be able to: Notes and guidance
Write code to perform file-processing operations Open (in read, write, append mode) and close a file Read a record from a file and write a record to a file Perform file-processing operations on serial, sequential, random files
Show understanding of an exception and the importance of exception handling Know when it is appropriate to use exception handling Write program code to use exception handling

来源:剑桥国际大纲

这扩展主题 10 的文件(file)处理,处理串行顺序随机(直接存取)文件。伪代码操作:OPENFILE name FOR READ | WRITE | APPEND(READ 打开一个现有文件,WRITE 创建/覆盖,APPEND 加到末端);READFILE name, line;WRITEFILE name, value;CLOSEFILE name;以及 EOF(name),它在末端为 TRUE。

读整个文件:

OPENFILE "names.txt" FOR READ
WHILE NOT EOF("names.txt") DO
    READFILE "names.txt", thisName
    OUTPUT thisName
ENDWHILE
CLOSEFILE "names.txt"

搜索一个文件(找到时停止):

found ← FALSE
OPENFILE "people.txt" FOR READ
WHILE NOT EOF("people.txt") AND NOT found DO
    READFILE "people.txt", line
    IF line = target THEN found ← TRUE
ENDWHILE
CLOSEFILE "people.txt"

Updating a file in place

大多数语言不能原地编辑一个文本文件。而是:打开原始文件为 READ、一个临时文件为 WRITE;对每行,若它应当改变就写新版本,否则写原始;关闭两者;然后用临时文件替换原始文件。同样的模式处理删除行(跳过它们)和插入行。

原地更新一个文件:读原始文件、把改动的行写到一个临时文件,然后用临时文件替换原始文件
原地更新一个文件:读原始、把改动写到一个临时文件,然后替换原始

Pitfalls

忘记关闭一个文件(数据可能丢失);本想 APPEND 却打开为 WRITE(覆盖一切);读过 EOF;硬编码的路径——一个像 /Users/Admin/data.txt 的路径在另一台机器上失效,所以用一个相对常量如 DataFile = "./data/scores.txt"

探索

File access route

Follow a file from storage to program and back safely.

词汇表 训练
英文 中文 拼音
file 文件 wén jiàn
20.2

异常处理

一个异常(exception)是执行期间的一个错误或意外情况——除以零、文件未找到、网络失败、一个数组(array)索引越界。异常处理(exception handling)让一个程序检测它并优雅地响应,而不是崩溃。

它重要是因为真实的程序面对无法事先预防的错误(文件被移动、网络中断、坏输入);没有它,每个操作都需要它自己的 IF 检查;而且它把正常流程与错误处理分开,所以主路径读起来干净。例如,一个文件可能在你的程序检查它存在和实际打开它之间被另一个用户删除——你无法预防那个,只能在它发生时处理失败。

Pattern

TRY
    OPENFILE "data.txt" FOR READ
    READFILE "data.txt", line
    OUTPUT line
    CLOSEFILE "data.txt"
EXCEPT FileNotFound
    OUTPUT "Sorry, the file does not exist."
EXCEPT ReadError
    OUTPUT "Sorry, error reading the file."
ENDTRY

TRY 块容纳可能失败的代码;第一个匹配的 EXCEPT 块运行。真实的语言也有一个包罗一切的 EXCEPT 和一个 FINALLY 块,它无论异常是否发生都运行——对清理(关闭文件)有用。

异常流程:若 TRY 块引发一个异常,控制跳到匹配的 EXCEPT;没有异常时它被跳过。无论哪种方式 FINALLY 块都运行,然后程序继续
异常流程:一个异常跳到匹配的 EXCEPT;FINALLY 总是在程序继续之前运行

Raising an exception

一个检测到错误的子程序能抛出(raise)一个异常,以便调用者处理它:

PROCEDURE Divide(a : INTEGER, b : INTEGER) RETURNS INTEGER
    IF b = 0 THEN
        RAISE DivideByZero
    ENDIF
    RETURN a DIV b
ENDPROCEDURE

Where to handle exceptions

若响应简单(一个消息、一次重试)就在贴近错误处处理它们,或若只有外层代码知道怎么做就在调用栈(call stack)更高处(一个顶层 GUI 循环记录错误并显示一个友好的对话框)。不要静默地吞掉异常——至少记录它们,否则调试变得不可能。

常见异常:FileNotFoundIOErrorDivisionByZeroIndexOutOfRangeInvalidArgumentNullReferenceOutOfMemory。把每个可能失败的操作包在一个带正确 EXCEPT 处理程序的 TRY 中,给出一个优雅降级而不是崩溃的程序。

例题。 一个会员文本文件需要修改某位会员的电话号码。为什么程序不能直接覆盖那一行?正确的模式是什么?文本文件中各行的长度不同,而文件中并没有空隙来吸收长度差:更长的新内容会侵入下一条记录,更短的则会把旧行的尾巴留在那里。所以正确的模式是:以方式打开原文件,以方式打开一个临时文件,逐行读取,对需要修改的那一行写入版本,其余各行则写入原来的内容,关闭两个文件,然后用临时文件替换原文件。删除(跳过该行)和插入(多写一行)也是同样的套路。注意每一行都要被写出,而不是只写改动的那一行 - 只写新记录、把文件其余部分弄丢,是经典的失误。

探索

How exception handling flows

Step through what happens when code fails. The exception jumps out of the normal flow to a handler, FINALLY cleans up either way, and the program carries on instead of crashing.

词汇表 训练
英文 中文 拼音
array 数组 shù zǔ
exception 异常 yì cháng
exception handling 异常处理 yì cháng chǔ lǐ
raise 抛出 pāo chū
call stack 调用栈 diào yòng zhàn
20.2

考试技巧

  • 区分各范式(过程式、面向对象、声明式、低级)以及每个何时适合一个问题。
  • 对于 OOP,用一个短例子定义类、对象、继承、封装和多态
  • 解释异常处理(try/catch)以及为什么它胜过让程序崩溃。

本主题的互动课程

逐步学习,并即时检测练习。

A-Level 计算机科学历年真题

A-Level 计算机科学的更多主题

登录或创建账号

IGCSE, A-Level & AP