天涯论坛

 找回密码
 立即注册
搜索
查看: 52|回复: 5

Python 到底是强类型语言,还是弱类型语言?

[复制链接]

3132

主题

2万

回帖

9996万

积分

论坛元老

Rank: 8Rank: 8

积分
99968646
发表于 2024-8-17 07:42:19 | 显示全部楼层 |阅读模式

0、前言

我在上一篇文案中分析了 为何 Python void 类型 的专题,在文案发布后,有读者跟我讨论起了另一个关于类型的问题,然则咱们火速显现了重大歧义

咱们重点歧义就在于:Python 到底是不是强类型语言? 我认为是,而他认为不是。

他写了一篇很长的文案《谁告诉的你们Python是强类型语言!站出来,保准不打你!》,专门重申了他的观点,但可惜错漏百出。

我曾有想法要写写关于 Python 类型的问题,此刻借着这个机会,就来系统地梳理一下吧。

(PS:在我写作进行到差不多一半的时候,微X读者群里恰好讨论到“强弱类型”的专题!在与大众讨论时,我的有些想法得到了验证,同期学到了很多新知识,因此本文的部分内容有群友们的功劳,特此鸣谢!)

1、动静类型与强弱类型

非常多读者应该都熟练动态类型 与静态类型 ,然则非常多会把它们跟强弱类型 混为一谈,因此咱们有必要先作一下概念上的澄清。

这两组类型都是针针对编程语言而言的,但关注的核心问题区别

针对“动静类型”概念,它的核心问题是“什么时候晓得一个变量是哪种类型”?

通常而言,在编译期就确定变量类型的是静态类型语言,在运行期才确定变量类型的则是动态类型语言。

例如,某些语言中定义函数“int func(int a){…}”,在编译时就能确定晓得它的参数和返回值是 int 类型,因此是静态类型;而典型如 Python,定义函数时写“def func(a):…”,并不晓得参数和返回值的类型,仅有到运行时调用函数,才最后确定参数和返回值的类型,因此是动态类型

针对“强弱类型”概念,它的核心问题是“区别类型的变量是不是准许隐式转化”?

通常而言,编译器有很少(恰当)隐式类型转化的是强类型语言,有较多(过分)隐式类型转化的是弱类型语言。

例如,Javascript 中的 "1000"+1 会得到字符串“10001”,而 "1000"-1 则会得到数字 999,便是说,编译器按照运用场合,对两种区别类型的对象分别做了隐式的类型转化,然则类似的写法,在强类型语言中则会报类型出错。(数字与字符串的转化属于过分的转化,下文会再说到有些恰当的转化。)

根据以上的定义,有人将平常的编程语言画了一张归类图:

按强弱类型维度的划分,能够归纳出:

强类型:Java、C#、Python、Ruby、Erlang(再加GO、Rust)……弱类型:C、C++、Javascript、Perl、PHP、VB……

2、过去的强弱类型概念

动静类型的概念基本上被大众所认可,然而,强弱类型的概念在问答社区、技术论坛和学术讨论上却有非常多的争议。此处就不作陈列了。

为何会有那样多争议呢?

重点原由之一是有人把它与动静类型混用了。

显著的一个例子便是 Guido van Rossum 在 2003 年参加的一个访谈,它的专题恰好是关于强弱类型的(Strong versus Weak Typing):

然则她们谈论的显著只是动静类型的区别。

访谈中还引述了 Java 之父 James Gosling 的话,从他的表述中能看出,他说的“强弱类型”其实是动静类型的区分。

另一还有一个经典的例子,C 语言之父 Dennis Ritchie 曾经说 C 语言是一种“强类型然则检测的语言。倘若对照成前文的定义,那他其实指的是“静态类型弱类型”。

为何这些大佬们会有混淆呢?

其实原由很简单,便是在当时还知道的动静类型与强弱类型的概念之分!说,那时候的强弱类型指的便是动静类型。

维基百科上给出了 1970 年代对强类型的定义,基本能够还原成前文说到的静态类型:

In 1974, Liskov and Zilles defined a strongly-typed language as one in which "whenever an object is passed from a calling function to a called function, its type must be compatible with the type declared in the called function."[3] In 1977, Jackson wrote, "In a strongly typed language each data area will have a distinct type and each process will state its communication requirements in terms of these types."[4]

前面几位编程语言之父应该便是持有类似的观念。

不外,大佬们认识到了当时的“强弱类型”概念并不充分准确,因此 Dennis Ritchie 才会说成“强类型然则检测”,况且在访谈中,Guido 尤其强调了 Python 不该该被叫作为弱类型,而应该说是运行时类型(runtime typing)

然则在那个初期年代,基本上强弱类型就等同于动静类型,而这般的想法迄今仍在影响着非常多人。

3、此刻的强弱类型概念

初期针对编程语言的归类其实是混杂了动静与强弱两个维度,然则,它们并不是一一对应重合的关系,并不足以表达编程语言间的区别,因此呢必须有更为知道/丰富的定义。

有人提出了“type safety”、“memory safety”等区分维度,显现了静态检测类型和动态检测类型,与强弱类型存在必定的交集。

直到显现 2004 年的一篇集大成的学术论文《Type Systems》(出自微软科研院,作者 Luca Cardelli),专门科研编程语言的区别类型系统:

论文中针对强弱检测即强弱类型)有一个简短的归纳如下:

Strongly checked language: A language where no forbidden errors can occur at run time (depending on the definition of forbidden error).Weakly checked language: A language that is statically checked but provides no clear guarantee of absence of execution errors.

其关键则是程序针对 untrapped errors 的检测强度,在某些实质已出错的地区,弱类型程序并不作捕捉处理,例如 C 语言的有些指针计算和转换,而《C 程序员十诫》的前几个都是弱类型引起的问题。

论文针对这些概念的定义还是比较抽象的,因为捕捉的错误(untrapped errors)大大都是因为隐式类型转换导致因此又演化出了第1节中的定义,以隐式类型转换做为判断标准。

如今将“对隐式类型转换的容忍度”做为强弱类型的归类标准,已然非常多人的共识(虽然不足全面,况且有些区别的声音)。

例如,维基百科就把隐式类型转换做为弱类型的重点特点之一:

A weakly typed language has looser typing rules and may produce unpredictable results or may perform implicit type conversion at runtime.

例如,以 Python 为例,社区的主流看法认为它是强类型语言,而判断的标准是看隐式类型转换。

例子有非常多例如 Python 官方的 wiki,它专门回答了Why is Python a dynamic language and also a strongly typed language ,给出了 4 个答案,为 Python 的“动态强类型”定性:

例如,在《流畅的Python》第11章的杂谈中,专门说到了强弱类型的归类。(它的用语是“很少隐式类型转换”,算是比较严谨的,然则错误地把 C++ 归为了强类型。)

4、Python 是不是强类型语言?

关于“Python 是不是属于强类型”专题,在主流观点之外,还存在着不少误解的看法。

一方面的原由有些人混用了强弱类型与动静类型,这有历史的原由,前面已然分析了。

另一还有一个一样重要的原由,即有人把弱类型等同于“完全隐式类型转换”了,这种想法并不对。

事实上,强弱类型的概念中包括着部分相对主义的含义,强类型语言中可能有隐式类型转换。

例如,Rust 语言为了实现“内存安全”的设计哲学,设计了很强大的类型系统,然则它里面有隐式类型转换(自动解引用)。

问题在于:怎么样的隐式类型转换是在恰当范围内的?以及,某些表面的隐式类型转换,是不是真的是隐式类型转换?

回到 Python 的例子,咱们能够分析几种典型的用法。

例如,"test"*3 这种字符串“乘法”运算,虽然是两种类型的操作,然则并不触及隐式类型转换转化。

例如,x=10; x="test" 先后给一个变量区别类型的赋值,表面上看 x 的类型变化了,用 type(x) 能够判断出区别然则,Python 中的类型是跟值绑定的(右值绑定),并不是跟变量绑定的。

变量 x 准确地说只是变量名,是绑定到实质变量上的一个标签,它类型。type(x) 判断出的并不是 x 本身的类型,而是 x 指向的对象的类型,就像内置函数 id(x) 算出的不是 x 本身的位置,而是实质的对象的位置

例如,1 + True 这种数字与布尔类型的加法运算,出现隐式类型转换。由于 Python 中的布尔类型其实是整型的子类,是同一种类型!(倘若有疑问,可查阅 PEP-285)

例如,整数/布尔值与浮点数相加,在 Python 中必须作显式类型转换。然则,它的实现过程其实是用了数字的__add__() 办法,Python 中一切皆对象,数字对象有自己的办法。(其它语言可不必定

便是说,数字间的算术运算操作,其实是一个函数调用的过程,跟其它语言中的算术运算有着本质的区别。

另一区别的数字类型虽然在计算机存储层面有很大差异,但在人类眼中,它们是同一种类型(宽泛地分),因此就算出现了隐式类型转换,在规律是可以接受的。

最后,还有一个例子,即 Python 在 if/while 之后的真值判断,我之前分析过它的实现原理 ,它会把其它类型的对象转化成布尔类型的值。

然则,它实质只是函数调用的结果(__bool__() 和 __len__()),是经过计算而得出的恰当结果,并不属于隐式的强制类型转换,不在 untrapped errors 的范畴里。

因此,严格来讲,前面 5 个例子中都出现类型转换。 浮点数和真值判断的例子,直观上看是出现了类型转换,但它们其实是 Python 的特性,是可控的、符合预期的、并对原有类型导致破坏。

退一步讲,若放宽“隐式类型转换”的含义,认为后两个例子出现了隐式类型转换,然则,它们是经过严谨的函数调用过程实现的,不会显现 forbidden errors,因此还是属于强检测类型。

5、其它关联的问题

前文对概念的含义以及 Python 中的表现,作了细致的分析。接下来,为了规律专题的完整性,咱们必须回答几个小问题:

(1)能否以“隐式类型转换”做为强弱类型的分类依据?

知道归类定义应该以《Type Systems》为准,它有一套针对区别 error 的归类,强弱类型其实是针对 forbidden errors 的处理归类。隐式类型转换是其显著的特征,但并不是所有不是独一的判断依据。

本文为了方便理解,运用这个重点特征来划分强弱类型,然则要强调,强类型不是隐式类型转换,而是可能有很少且恰当的隐式类型转换。

(2)假如有其它解释器令 Python 支持广泛的隐式类型转换,那 Python 还是强类型语言么?

语言的标准规范就像是法律,而解释器是执法者。倘若有错误的执法解释,那法律还是那个法律,应该改掉错误的执法行径倘若是法律本身有问题(造成为了解释歧义和矛盾,该废弃),那就应该修改法律,保准它的确定性(要么是强类型,要么是弱类型)。

(3)为何说 Javascript 是弱类型?

由于它的隐式类型转换非常多、非常繁杂、非常过分!例如,Javascript 中123 + null 结果为 123,123 + {} 结果为字符串“123[object Object]”。

另一,它的双等号“==”除了有基本的比较操作,还可能出现多重的隐式类型转换,例如true==[2] 判断出的结果为 false,而true==[1] 的结果是 true,还有[]==![] 和[undefined]==false 的结果都为 true……

(4)C++ 是不是弱类型语言?

前文说到《流畅的Python》中将 C++ 归为强类型,但实质上它应该被归为弱类型。C++ 的类型转换是个非常繁杂专题,@樱雨楼 小姐姐曾写过一个系列文案做了系统论述,文案位置怎样解决 C++ 中繁杂的类型转换? 、详解 C++ 的隐式类型转换与函数重载! 、谁说 C++ 的强制类型转换很难懂?

6、小结

强弱类型概念在网上有比较多的争议,不仅在 Python 是如此,在 C/C++ 之类的语言更甚。

其实在学术上,这个概念早已有知道的定义,况且事实上非常多人所接纳。

哪些反对的声音大大都是由于概念混用,由于她们忽略了另一种对语言进行归类的维度;同期,还有一部分值得重视原由,即不可认为强类型等于“完全无隐式类型转换”或“只要xxx隐式类型转换”。

本文介绍了社区中对 Python 的主流归类同期对几类疑似隐式类型转换的用法进行了分析,论证出它是一种强类型语言。

文案表现了作者一贯的刨根问底精神,这是“Python为何”系列文案的风格,倘若爱好本文,欢迎订阅关注!

关联链接

[1] 谁告诉的你们Python是强类型语言!站出来,保准不打你!:

https://blog.csdn.net/nokiaguy/article/details/108218260

[2] Strong versus Weak Typing: https://www.artima.com/intv/strongweak.html

[3] https://en.wikipedia.org/wiki/Strong_and_weak_typing#cite_note-2

[4] https://en.wikipedia.org/wiki/Strong_and_weak_typing#cite_note-3

[5] Type Systems: http://lucacardelli.name/Papers/TypeSystems.pdf

[6] C 程序员十诫:

http://doc.cat-v.org/henry_spencer/ten-commandments

[7] Why is Python a dynamic language and also a strongly typed language: https://wiki.python.org/moin/Why%20is%20Python%20a%20dynamic%20language%20and%20also%20a%20strongly%20typed%20language

[8] PEP-285: https://github.com/chinesehuazhou/peps-cn/blob/master/StandardsTrack/285--%E6%B7%BB%E5%8A%A0%E5%B8%83%E5%B0%94%E7%B1%BB%E5%9E%8B.md

[9] Type Systems: http://lucacardelli.name/Papers/TypeSystems.pdf

[10] Python为何:

https://github.com/chinesehuazhou/python-whydo




上一篇:你认为Python少儿编程有用吗?【揭秘儿童编程的黄金语言】
下一篇:python属于什么类型语言
回复

使用道具 举报

1

主题

520

回帖

5

积分

新手上路

Rank: 1

积分
5
发表于 2024-8-20 18:37:46 | 显示全部楼层
楼主的文章非常有意义,提升了我的知识水平。
回复

使用道具 举报

1

主题

792

回帖

-3

积分

限制会员

积分
-3
发表于 2024-9-10 03:39:41 | 显示全部楼层
这夸赞甜到心里,让我感觉温暖无比。
回复

使用道具 举报

3085

主题

2万

回帖

9909万

积分

论坛元老

Rank: 8Rank: 8

积分
99098784
发表于 2024-10-8 13:06:04 | 显示全部楼层
外链论坛的成功举办,是与各位领导、同仁们的关怀和支持分不开的。在此,我谨代表公司向关心和支持论坛的各界人士表示最衷心的感谢!
回复

使用道具 举报

3042

主题

2万

回帖

9606万

积分

论坛元老

Rank: 8Rank: 8

积分
96065870
发表于 2024-10-13 10:37:39 | 显示全部楼层
太棒了、厉害、为你打call、点赞、非常精彩等。
回复

使用道具 举报

3057

主题

2万

回帖

9913万

积分

论坛元老

Rank: 8Rank: 8

积分
99139068
发表于 2024-11-12 07:17:23 | 显示全部楼层
你的见解独到,让我受益匪浅,非常感谢。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站点统计|Archiver|手机版|小黑屋|天涯论坛 ( 非经营性网站 )|网站地图

GMT+8, 2024-11-22 10:21 , Processed in 0.122075 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.