当前位置: 首页 > 科技观察

为什么Python不支持i++自增语法,也不提供++运算符?

时间:2023-03-13 05:11:54 科技观察

在C/C++/Java等语言中,整型变量的自增或自减操作是标准的,可分为前缀操作(++i和--i)和后缀操作(i++和i--)之间存在一些细微差别,并且每个都有不同的用途。这些语言的使用者在接触Python的时候,可能会疑惑为什么它不提供++或者--操作呢?虽然Python中可能会出现++i的前缀形式,但它没有“++”自增运算符,只是两个“+”(正数符号)的叠加。至于后缀“++”,则完全不支持(SyntaxError:invalidsyntax)。本期“WhyPython”专栏,我们将从两个主要角度进行解答:为什么Python不支持i++自增语法?(PS:自增指的是“自增自减”,下同)首先,Python当然可以实现自增效果,即可以写成i+=1或者i=i+1,这在其他语言中也很常见。尽管Python使用不同的魔术方法(__add__()和__iadd__())在底层进行计算,但表面效果是完全一样的。因此,我们的问题可以转化为:为什么以上两种写法都比i++好,成为Python的最终选择?1.Python整数是不可变类型。当我们定义i=1000时,不同的语言会做出不同的处理:比如C语言(写成inti=1000)会申请一块内存空间,给它“绑定”一个固定的名字i,然后写一个同时变量值1000。这里,i的地址和类型是固定的,但值是可变的(在一定的表示范围内)。Python(写i=1000)也会申请一块内存空间,但是会“绑定”到数字1000上,即1000的地址和类型是固定的(不可变的),至于i,就是只是给1000贴了个名字标签,它本身没有固定的地址和类型,所以当我们让i“自增”(i=i+1)时,他们的处理是不同的:C等语言先找到i的地址存储的值,然后将其加1,运算后新值替换旧值。Python的操作过程是指向i的数字加1,然后将结果绑定到一块新申请的内存空间,然后将名字标签i“贴”到新的数字上。新旧号码可以同时存在,不是替换关系。一个不恰当的类比:C中的i就像一个宿主,数字1000寄生在它上面;而Python中的1000就像一个主机,名字i寄生在它上面。C中的i和Python中的1000是寄生在底层内存空间上的……也可以这样理解:C中的变量i是一等公民,数字1000是它的变量属性;数字1000是一等公民,名字i是它的可变属性。有了上面的铺垫,我们再来看看i++。不难发现:在C等语言中,i++可以代表i数字属性的增加,不会开辟新的内存空间,也不会在语言中创建新的一等公民比如Python,如果i++是对其name属性的操作,那么就没有意义了(不能按字母顺序把i改成j);如果理解为对数字本体的操作,那么情况就会变得复杂:它会生成一个新的一等公民1001,所以需要为其分配一个内存地址。如果此时1000的地址被占用,就会涉及到旧对象的回收,影响到原来对1000的引用关系。因此,我们只能为1001开辟新的内存空间。如果Python支持i++,其运算过程比C的i++复杂,其意义不再是“数字加1”(自增),而是“创建新数”(new),在这种情况下,“增量运算符”(incrementoperator)名不副实。Python理论上可以实现i++运算,但必须重新定义“自增运算符”,这也会给有其他语言经验的人造成误解。还是让大家直接写i+=1或者i=i+1好吧。2.Python有可迭代的对象。C/C++等语言设计i++,主要目的是为了方便使用三阶段for结构:for(inti=0;i<100;i++){//executexxx}这个程序关注随着数字本身的自增过程,数字的增加与程序体的执行相关联。Python中没有for结构的这种写法,提供了更优雅的写法:foriinrange(100):#Executexxxmy_list=["你好","我是Python猫","欢迎关注"]forinfoinmy_list:print(info)这里反映了一种不同的思维方式。它关心的是在一个取值范围内的迭代遍历,不关心也不需要人为加数字。Python中的Iterableobjects/iterators/generators提供了非常好的迭代/遍历用法,可以完全替代i++。比如上面的例子,实现了对列表中值的遍历。Python也可以使用enumerate()同时实现下标和具体值的遍历:my_list=["你好","我是一只Python猫","欢迎关注"]fori,infoinenumerate(my_list):print(i,info)#打印结果:0你好1我是Python猫2欢迎关注。例如,对于字典的遍历,Python提供了keys()、values()、items()等遍历方法很有用:my_dict={'a':'1','b':'2','c':'3'}forkeyinmy_dict.keys():print(key)forkey,valueinmy_dict。items():print(key,value)这么强大的工具,i++用在什么地方?不仅如此,i+=1或i=i+1在Python中很少使用,因为有了随处可见的可迭代对象,开发人员很容易实现对一个值范围的操作,并且有对积累一定价值的需求不大。那么,回到我们一开始的问题,其实这两种“自增”的写法并没有比i++好多少,只是因为它们是通用运算,不需要引入新的运算符,所以Python继续一个基本支持。真正的赢家其实是各种可迭代对象!一点总结:Python不支持自增运算符。一方面,这是因为它的整数是不可变类型的一等公民。如果自增操作(++)支持的话,会带来歧义;另一方面主要是因为它有更合适的实现,可以迭代对象,对遍历操作有很好的支持。