python 进阶(13) -- python 是一种怎样的语言


你曾经是谁的英雄呢


转载

http://mp.weixin.qq.com/s/KbEjTm5jRs7tBNP3ZZck4Q


前言

「当我们在使用一个工具时,首先要做的就是尝试去了解它。」

面试题:解释/编译?动态/静态?强/弱?Python 到底是一门怎样的语言


编译 or 解释

编译、解释都是指将(与人类亲和的)编程语言翻译成(计算机能够理解的)机器语言(Machine code)的过程。它们有什么区别呢?看一个例子:

Emmmmmmmmmmmmm~ 神比喻 !!

没错,编译型语言会将全部源代码一次性翻译完成,最终得到可执行文件,所以其主要特征为「一次编译,多次执行」,虽然编译时间长,但运行效率奇高,毕竟可执行文件就是一连串可以被计算机直接执行机器指令集。但缺点是可移植性差(异构平台的 CPU 指令集不兼容)、编译耗时与程序规模成正比,而且每次修改源码都要重新编译,所以 debug 体验糟糕。典型的编译型语言有 C/C++,常见于偏底层,执行环境苛刻且追求速度的场景(e.g. 嵌入式、硬件开发、矿工);

反观解释型语言并不会直接将源码翻译成机器码,而是先翻译成中间码,再交由语言自身提供的解释器逐条解释执行,所以解释型语言的特征之一就是「边解释,边执行」,导致了解释型程序的运行效率会更低。解释,或者说解释器存在的目的是为了提供一个与平台无关的托管运行时环境,使同一个程序能够运行在不同的操作系统之上,这就是解释型型语言的另一大特征「跨平台」。

值得注意的是,Python 因为含有解释器,所以常被归类为解释型语言。实际上这一论断并不严谨,因为 Python 程序的运行同样需要经历编译的过程。Python 自身也包含了编译器,它会将源码先编译为中间状态的字节码(Bytecode),再由解释器解释。默认的,Python 会将这些字节码保存在临时文件 .pyc 中,以避免重复进行编译,直到下一次源码修改为止。

这样做的根本目的是为了在支撑跨平台的基础上进一步提升程序的运行效率,也正因如此使得编译和解释的界限变得模糊。如果单纯的将 Python 定性为解释型语言,难免会造成理解上的缺失。比如,不了解 .pyc 文件存在的意义。

所以,我更愿意将 Python 定义为一门既有编译又有解释的更高级的编程语言。


动态 or 静态

动态、静态指的是编程语言类型系统对数据类型检查的严格程度。

静态类型语言会进行严格的数据类型检查,在程序编译时(compile time),就需要确定所有变量的数据类型,所以静态类型语言强制要求在使用变量之前事先声明变量的数据类型。因为类型声明机制,静态类型语言的编译器或 IDE 能够拥有良好的代码感知能力,使程序员更易于开发出复杂且庞大的应用系统程序。典型代表有 C、Java。

int anInt;
char aString[10];
anInt = 1;
aString = {"a","b","c","d","\0”};

动态类型语言则相反,属于非严格数据类型检查。程序在实际运行时(runtime),变量的数据类型才被确定。典型代表就是 Python

>>> obj = 123
>>> obj = 'abc'

动态类型语言不需要类型声明,同一个变量可以在不同的位置被赋予各种数据类型。只有当程序执行到某条具体的赋值语句时,变量类型才会由赋值对象的数据类型决定。因此,Python 程序的开发具有很强的灵活性,同时开发效率也不是 Java 能够比拟的。不过,虽然 Python 程序员可以不关注变量的数据类型,但解释器却需要去推断变量的数据类型,这也在一定程序上影响了程序的运行效率。而且数据类型检查不严格,也更容易埋下不易察觉的 bug。所以,Python 更适合开发中小型应用系统


强类型 or 弱类型

强、弱类型指的是编译程序时能否容忍隐式的数据类型转换

弱类型语言能够容忍在程序运行时对变量进行隐式的数据类型转换,是一种几乎可以忽略数据类型的编程语言。可见,弱类型语言是类型非安全的。例如 JavaScript:

> '1' + 2
'12'

强类型语言则相反,它是类型安全的。变量的数据类型一旦被确定,除非使用强制类型转换,否则其数据类型永远不会改变。强类型语言在速度上会稍逊于弱类型语言,但强类型带来的严谨性能够更好的避免许多错误。例如 Python:

>>> '1' + 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int’ objects

那类型安全具有什么意义呢?

描述类型安全系统的最简单的方法就是描述它的对立面。有的语言(尤其是C和C++)允许做一些非常“不正当”的事情。但在合适的时候,其功能可能会很强大。但是,世界上没有免费的午餐。所谓“合适的时候”实际很少能够遇到。如使用不当,反而极有可能“搬起石头砸自己的脚”。滥用类型系统就属于这种情况

打个比方,当程序将一个变量当作类型 A 来执行时,却意外的发现这个变量可能是类型 B,也可能什么都不是。但此时的程序可能已经通过了编译,正在运行的阶段。在这样的情形下,就很可能会导致程序崩溃或异常退出的问题。

当然了,这里描述的是编程语言的类型安全问题。但很多时候即便编程语言是类型安全的,也可能会实现出类型非安全的应用程序,这属于两个层面的事情。所以即便 Python 是类型安全的,我们仍需谨慎的处理数据类型问题


最后

对于此次的面试题,我们可以简单的用一句「Python 是一门动态的强类型解释语言」来回答,但这样难免流于表面。我们通过对比编程语言的「编译/解释、动态/静态、强/弱」等类型特征之后应该可以更深刻的理解 Python 的语言特性。

  • Python 具有非常好的跨平台特性,同一套代码能够在不同的平台上正常的运行;

  • Python 虽然在编译上作出了努力,但同比其他编程语言依旧会慢;

  • Python 编程很灵活、效率很高,为此也牺牲了代码的严谨性,不适合多人协同开发大规模应用程序;

  • Python 虽然是类型安全的编程语言,但因其太多灵活,所以很容易实现出类型非安全的应用程序;