# 简介
- 程序:本质上是一组计算机指令代码,能让计算机执行某种操作。
- 编程:泛指编写计算机程序的过程。
- 编写程序代码之后,再执行程序代码,即可控制计算机完成某些任务。
- 编程语言:泛指可用于编写程序代码的语言。
# 语言分类
# 机器、汇编、高级
将编程语言根据可读性分类:
- 机器语言
- :由二进制代码 1 和 0 组成,几乎没有可读性。
- 能直接被计算机识别、执行,但是不能移植到不同操作系统上运行。
- 汇编语言
- :用助记符编写程序,又称为符号语言。有基本的可读性,但是仍然难以记忆。
- 汇编语言编写的代码要通过汇编(即翻译)转换成机器语言才能运行。
- 高级语言
- :模仿自然语言的语法进行编程,可读性好。
- 与高级语言相比,机器语言和汇编语言都是低级语言。
# 编译、解释、脚本
将编程语言根据运行方式分类:
- 编译型语言
- :代码通过编译器(先翻译再执行)转换成机器语言之后才能运行。比如 C、C++ 语言。
- 缺点:程序在编译之后几乎不能移植。
- 解释型语言
- :代码不需要编译,在运行时才通过解释器(边翻译边执行)转换成机器语言。比如 Java、C# 语言。
- 优点:程序容易移植到不同平台。
- 脚本语言
- :属于解释型语言、动态语言。比如 Shell、Python 语言。
- 优点:可以不编译就即时执行代码,可以逐行执行代码,便于调试。
- 一般而言,编译型语言、解释型语言、脚本语言的运行速度、效率依次递减。
- 脚本语言刚诞生时功能较少,如今已经进化得像编译型语言一样功能强大。而且现在计算机硬件性能提升了很多,使用脚本语言也可以达到很好的性能。
# GPL、DSL
将编程语言根据使用场景分类:
- 通用编程语言(General Purpose Language ,GPL)
- 可用于多种领域,用途较广。
- 领域特定语言(Domain Specific Language , DSL)
- 主要用于个别领域,但在该领域的使用效果可能比通用编程语言更好。
- 例如用于描述 Web 页面的 HTML、CSS 语言,用于数据库结构化查询的 SQL 语言,用于匹配字符串的正则表达式,用于 Linux 终端操作的 Shell 语言。
# 语法分类
# 弱类型、强类型
根据变量赋值、运算时,能否自动转换数据类型来分类:
- 弱类型
- :支持自动转换数据类型。
- 例如在 C 语言中可执行以下语句:
float x = 1;
- 强类型
- :不支持自动转换数据类型。
- 一种编程语言可能同时具有强类型、弱类型的语法。例如在 Python 中:
>>> x = 1 >>> x = '1.0' # 同一个变量可以执行不同类型的赋值,这是因为改变了变量引用的对象,体现了 Python 是动态类型语言 >>> 1 + '1.0' # 不同类型的值不支持混合运算,体现了 Python 是弱类型语言,但用户可以重载 __add__() 方法来实现混合运算 TypeError: unsupported operand type(s) for +: 'int' and 'str'
# 静态类型、动态类型
根据程序运行时,能否改变变量的数据类型来分类:
- 静态类型语言(statically typed language)
- :在程序编译之后,变量的数据类型不能改变。
- 通常在程序编译时就检查数据类型,如果数据类型不符合要求,则中断编译,并报错。
- 动态类型语言(dynamically typed language)
- :在程序编译之后,变量的数据类型可以改变。
- 通常在程序运行时才检查数据类型,如果数据类型不符合要求,可能报错,也可能自动转换数据类型。
- 优点:使用变量时可以很灵活。
- 缺点:数据类型不符合要求时,如果不报错,导致问题被用户忽略,则可能引发更大的问题。
# 静态编程、动态编程
根据程序运行时,能否改变程序结构来分类:
- 静态编程语言(dynamic programming language)
- :在程序编译时确定了程序结构,不能改变。
- 简称为静态语言。大部分静态语言属于静态类型语言。
- 动态编程语言(dynamic programming language)
- :在程序运行时可以改变程序结构,比如改变函数、改变代码。
- 简称为动态语言。大部分动态语言属于动态类型语言。
- 鸭子类型(duck typing):如果一只鸟走起来像鸭子,游起来像鸭子,叫起来也像鸭子,那它就是一只鸭子。
- 鸭子类型体现了动态语言的特点:只要一个类提供了鸭子类该有的属性和方法 walk()、swim()、quack() ,就可以将它当作一个鸭子类使用。
# 编程范式
编程范式(Programming Paradigms):泛指编写代码的风格。有的编程语言的语法较自由,支持多种编程范式;有的编程语言的语法较严格,只支持特定的编程范式。
# 面向过程编程
:Process-oriented Programming 。指按解决问题的步骤一步步编写代码。
- 优点:流程简单、稳定。
- 缺点:前后代码高度耦合,可扩展性差。
# 面向对象编程
:Object Oriented Programming(OOP)。指将代码封装成类,抽象化。
- 优点:能大大提高代码的复用性,便于编写大型程序。
- 缺点:一个类下的各个方法之间容易耦合,有继承关系的类之间容易耦合。因此维护一个类的成本比维护一个函数大很多。
# 结构化编程
:Structured Programming 。指编程时采用顺序、选择、循环、递归等控制结构,自顶向下,逐步设计。
- 将一个语句块视作一个语句处理。
- 是对面向过程编程的改进,使流程更清晰。
# 函数式编程
:Functional Programming 。编写函数时像编写数学函数,主要考虑给定输入参数时返回什么值,不会主动影响函数外部,不会影响程序的行为。
- 使函数高度解耦,常用于声明式编程。
# 命令式编程
:Imperative Programming 。主要考虑让程序执行什么操作,从而得到某种结果。
- 代码面向过程,很流程化,可扩展性差。
- 例如脚本语言。
# 声明式编程
:Declarative Programming 。主要描述想得到什么结果,不考虑程序的具体操作。
- 例如 SQL 语言、正则表达式。
# 符号式编程
:Symbolic Programming 。可以定义实现某种功能的表达式。
- 与函数相比,这样的代码更接近数学表达式,更直观。
- 例如 Lisp 语言中用表达式
(+ 1 2)
来求和,而不是函数sum(1, 2)
。
# 元编程
:Meta Programming 。指程序运行时可以修改自己或其它程序的代码。
- 所有编译器、解释器、DSL 都属于元编程,一般语言的反射、泛型也属于元编程。
# 相关概念
# 耦合度
:Coupling ,指程序或代码之间联系的紧密程度,影响到它们能否独立运行。
- 比如程序 A 运行时需要调用程序 B ,代码 A 运行时需要读取代码 B 中的变量。
- 在模块化编程时,应该尽量降低耦合度,便于随时更换模块,提高可扩展性。
# 语法糖
:Syntactic Sugar 。泛指一些提升代码的可读性的语法,但不一定能优化程序的运行效率。
- 例如 Python 中的列表生成式。
# API、ABI
API(Application Programming Interface ,程序编程接口)
- 指一个程序提供的某个接口,可供其它程序在代码中调用,用于实现某种功能。例如:
- 一个 C 语言程序可以在头文件中声明函数形式的 API ,供其它程序调用。
- 一个 Web 服务器可以提供 HTTP 形式的 API ,供其它程序发出 HTTP 请求来调用。
- 如果一个程序提供了某个 API ,另一个程序也提供了相同的 ABI ,则其它程序可以通过相同的方式(比如用同一段代码)与这两个程序交互,称为兼容。
- 指一个程序提供的某个接口,可供其它程序在代码中调用,用于实现某种功能。例如:
ABI(Application Binary Interface ,程序二进制接口)
- 是比 API 更底层的概念,主要考虑编译成二进制形式的应用程序,如何与编译器、操作系统等底层软件交互。例如:
- 调用函数时是通过寄存器还是别的方式传递参数。
- 如何管理堆栈。
- 如何传递异常。
- 如果某两个操作系统的 ABI 兼容,则可以将其中一个操作系统上的二进制程序,拷贝到另一个操作系统上运行。
- 是比 API 更底层的概念,主要考虑编译成二进制形式的应用程序,如何与编译器、操作系统等底层软件交互。例如: