当前位置: 首页 > 后端技术 > Python

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

时间:2023-03-25 19:27:49 Python

文章来源:Python猫作者:豌豆花猫在C/C++/Java等语言中,整型变量的自增或自减操作是标准的,可以分为前缀操作(++i和--i)和后缀操作(i++和i--),彼此之间有一些细微的区别,并且每个都有不同的用途。当这些语言的使用者接触到Python时,他们可能会疑惑为什么它不提供++或--操作?在我前不久发的《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++){//执行xxx}这种程序关注的是数字本身的自增过程,数字的加法与程序体的执行相关联。Python中没有这样的for结构,它提供了一种更优雅的方式:foriinrange(100):#Executexxxmy_list=["Hello","IamaPythoncat","Welcometoattention"]forinfo在my_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不支持自增运算符,一方面是因为它的整数是不可变类型的一等公民,如果要支持自增运算符(++),就会带来歧义;另一方面,主要是因为它有更合适的实现,即可迭代对象,对遍历操作有很好的支持。