# 简介
- 程序:本质上是一组计算机指令代码,能让计算机执行某种操作。
- 编程:泛指编写计算机程序的过程。
- 编写程序代码之后,再执行程序代码,即可控制计算机完成某些任务。
- 编程语言:泛指可用于编写程序代码的语言。
# 语言分类
# 机器、汇编、高级
将编程语言根据可读性分类:
- 机器语言
- :由二进制代码 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 。指按解决问题的流程,一步步编写代码。
- 这样编写的程序,会让 CPU 按顺序执行一行行指令。也可以将多行指令,封装为一个函数,然后调用该函数。
# 面向对象编程
:Object Oriented Programming(OOP)。指将实现某一功能的相关变量、函数,封装为一个类。
- 优点:
- 代码容易复用。使用同一个类,可以创建多个相似的对象,不必为每个对象分别编写一套代码。
- 可扩展性好。假设某个功能由某个类实现,如果想修改该功能,不必修改该类的源代码,可以继承该类,定义一个子类。
- 缺点:
- 开销更大。使用每个类时,必须先实例化,创建一个对象,分配一定内存。
- 同一个类的多个方法之间通常耦合,具有继承关系的多个类之间通常耦合,需要理清它们的耦合关系。
- 例:
- C 语言通常是编写函数,进行面向对象编程。也可以用 struct 结构体,进行面向对象编程,不过缺少继承、多态等语法。
- Java 语言支持多种面向对象的语法,擅长面向对象编程。类中的每个方法,相当于一个函数,属于面向过程编程。
- 现代的高级语言,大多支持面向对象编程,提供了三种基本语法:
- 封装
- 将实现某一功能的相关变量、函数,封装为一个类,从而集中到同一个命名空间,方便相互调用。
- 封装,有利于实现高内聚、低耦合的设计模式。
- 类中的函数,通常称为方法(method)。
- 类中的变量、函数,统称为该类的成员(member)。
- 继承
- 定义一个类时,允许继承另一个类的变量、函数,而不必将另一个类的源代码拷贝到当前类。
- 多态
- 同一个类中,允许几个方法的名称相同,但源代码、实现的效果不同。
- 封装
# 结构化编程
:Structured Programming 。指编程时采用顺序、选择、循环、递归等流程结构。
- 早期的编程语言,只支持面向过程编程,只能按顺序从上到下执行代码。虽然可以用 goto 跳转执行代码,但容易引发 bug 。
- 后来的编程语言,提供了多种流程结构。例如 if 语句属于选择结构,if 语句中的语句块可以包含多条语句,属于顺序结构。
# 函数式编程
:Functional Programming 。编写函数时像编写数学函数,主要考虑给定输入参数时返回什么值,不会主动影响函数外部,不会影响程序的行为。
- 优点:使函数高度解耦,常用于声明式编程。
# 符号式编程
:Symbolic Programming 。可以定义实现某种功能的表达式。
- 与函数相比,这样的代码更接近数学表达式,更直观。
- 例如 Lisp 语言中用表达式
(+ 1 2)
来求和,而不是函数sum(1, 2)
。
# 命令式编程
:Imperative Programming 。擅长向计算机发出各种指令。
- 例如 shell 脚本语言,提供了 mv 指令来移动计算机中的文件,不需要用户亲自编写一段代码来移动文件。
# 声明式编程
:Declarative Programming 。只管描述用户想得到什么结果,不考虑具体过程怎么做。
- 例如 SQL 语言,只管描述用户想从数据库获取什么数据,不管如何获取该数据。
- 例如正则表达式。
# 元编程
:Meta Programming 。指程序运行时可以修改自己或其它程序的代码。
- 所有编译器、解释器、DSL 都属于元编程,一般语言的反射、泛型也属于元编程。
# 相关概念
# 耦合度
:Coupling ,指两个代码之间的联系深浅,影响它们能否独立运行。
- 假设程序 A 运行时,必须调用程序 B ,则它们的耦合度高。
- 假设程序 A 运行时,可以调用程序 B ,也可以不调用,则它们的耦合度低。
- 在模块化编程时,应该尽量降低耦合度,便于随时更换模块,提高可扩展性。
# 语法糖
:Syntactic Sugar 。泛指一些提升代码的可读性的语法,但不一定能优化程序的运行效率。
- 例如 Python 中的列表推导式。