为什么 Python 不用声明类型?
作者:编程指北
来源:编程指北
变量为什么需要类型?
这个问题点像手机为什么叫手机,电脑为什么叫电脑,这种“日用而不知”的感觉。
为什么有些语言需要申明类型,而有些语言却不需要申明类型?
前者如 C/C++、Java,后者有 Python、JS 。
首先,在讨论为什么需要类型之前,先聊聊类型。
一、 类型
我们都知道,不管是中文、英文还是编程语言,都具有语法,语法规定了词怎么组成句子是符合规范的。
int a = 10;
是可以的,但是a int = 10;
却不符合 C 语法规范。
10 + 10
是正确的,但是10 + “hello”
却是一个无效的表达式,但是该怎么判定呢?
答案就是「类型系统」,类型系统可以构建起一套判断表达式是否合法的规则。
对于每个变量都赋予一个类型,对于每种类型都定义了一组操作集合,而变量作为类型的实例,自然的继承了这些操作。
比如我们可以规定int + int
、string + string
是合法的操作,直接禁止int + string
等操作。
通过显示的将变量赋予类型,我们便可以在编译时去检查是否合法。
二、 变量
之前我在指针的那篇文章种说到:变量名是变量地址的符号化,变量名是为了让我们编程时更加方便,对人友好,可计算机可不认识什么变量 a
,它只知道地址和指令。
所以当你去查看 C 语言编译后的汇编代码,就会发现变量名消失了,取而代之的是一串串抽象的地址。
可以认为,编译器会自动维护一个映射,将我们程序中的变量名转换为变量所对应的地址,然后再对这个地址去进行读写操作。
三、类型规定了什么?
我个人觉得类型首先是定义了一组操作,这是语法层面。
那所有的高级语言最后都会变成机器语言执行(解释型除外),再高级一点,那就是汇编,我们知道汇编语言是由一条条指令构成的。
而对于任何一条指令,最重要的有两点:数据的长度、数据在哪。
比如mov dest,src
将一个字节从源地址 src 传送到目的地址 dest。
实际上,数据在哪就是地址,数据长度其实某方面就是取决于类型。
也正是这样,我之前在指针那篇文章中提到:指针的本质就是存储别的变量的地址,那么指针的类型是干什么用的呢?
是的,就是去访问指针所指向的地址的时候,指针的类型和指针的值(变量地址),提供了一条汇编指令最关键的两点:数据的长度和数据地址。
所以,类型除了提供语法检查以外,还能够明确变量所占据的内存空间。
同样也是规定了对字节的解释方式,同样 4 个byte,按照 int 和 float 类型解释得到的值完全不同。
更为本质的是,最终执行指令的 CPU 是区分了数据的类型的,不同的类型用不同的运算器,比如有 CPU 整形运算和 CPU 浮点型运算,不过浮点运算最为擅长的应该是 GPU。
也正是因为 CPU 区分了类型,上层的汇编、高级语言才需要区分变量的类型,CPU 基础决定了上层建筑。
四、 编译型&解释型
为什么 C/C++、Java 这类编译型语言就需要显示声明类型,而 Python 这类解释型语言就不需要呢?
所以是所有的编译型都需要申明类型?所有的解释型都不需要?
这个理解是不对的。
首先,“编译”和“解释”是语言实现的特征, 语言本身可以以任何一种方式实现。
可能我们大多只了解过 C 编译器(如GCC 、Clang ),却很少听过 C 解释器,如 Ch。
但是,即使使用 Ch 解释器,我们任然需要在 Ch 解释的 C 代码中申明类型。
为什么 Python 可以不用申明类型?
因为 Python 中的对象模型本身在运行时自带了“类型”这个信息,下面是 CPython 源码中关于对象的定义:
这个ob_type
就是用来 Python 运行时检测变量类型的,而 Python 中的所有变量本质上都是一个对象的“指针”。
也正因为如此,Python 中的各种变量之间才能随意赋值,因为赋值的本质其实就是改变一下变量所指向的对象。
而真正到了解释执行的时候,Python 解释器就会取出这个类型字段,来判断操作是否符合语法,不符合的话就会运行时报错。
这个_typeobject
结构体的内部就定义了对象一系列的操作,比如 hashfunc、getattrfunc、setattrfunc
等。
那么,为什么 C 即使是解释执行也需要申明类型呢?
很简单,因为 C 的对象模型中不会有”类型“这个字段,是 int 变量那直接就是 4 个字节,char 就 一个字节。
而 Python 的 int 变量,除了4 个字节的值本身以外,还需要占据一系列的描述类型的空间。
也就是说 C 语言运行时完全没有类型这种信息,所以需要在编译、解释的时候就带上。
之前偶尔会听到有人说 Python 是无类型的,这是完全错误的,看过这篇文章后,相信你一定不会说错了。
当然了,本文也只是简单的从粗浅的语法和实现层面解释了下,关于类型系统、类型推导等有人在研究的,这个也不是咱擅长的地方,感兴趣可以去搜一下。
Python猫注:关于 Python 的类型话题,推荐阅读:《Python到底是强类型语言,还是弱类型语言?》、《辨析编程语言的四种类型:动静类型与强弱类型》
还不过瘾?试试它们