This original answer I wrote is a myth from the folklore of computing :Dennis Ritchie将其揭穿为"historically impossible",如2012年7月ACM通讯编辑的信中所述doi:10.1145/2209249.2209251
它就是这样设计的 . 增量和减量运算符只是 x = x + 1 的捷径 . Python通常采用一种设计策略,减少了执行操作的替代方法的数量 . Augmented assignment是最接近Python中递增/递减运算符的东西,它们甚至在Python 2.0之前都没有添加 .
36
我'm very new to python but I suspect the reason is because of the emphasis between mutable and immutable objects within the language. Now, I know that x++ can easily be interpreted as x = x + 1, but it LOOKS like you'就地增加一个可以是不可变的对象 .
In [19]: id(a)
Out[19]: 34019256
In [20]: id(b)
Out[20]: 34019256
In [21]: id(c)
Out[21]: 34019256
所有三个变量(标签)都指向到同一个对象 . 现在增加一个变量并查看它如何影响内存地址:
In [22] a = a + 1
In [23]: id(a)
Out[23]: 34019232
In [24]: id(b)
Out[24]: 34019256
In [25]: id(c)
Out[25]: 34019256
您可以看到变量 a 现在指向另一个对象作为变量 b 和 c . 因为你已经使用了 a = a + 1 ,所以它是明确的 . 换句话说,您完全指定另一个对象来标记 a . 想象一下,你可以写 a++ 它会建议你没有分配给变量 a new对象但是ratter增加旧对象 . 所有这些东西都是恕我直言,以尽量减少混乱 . 为了更好地理解python变量的工作原理:
这可能是因为@GlennMaynard正在考虑与其他语言相比较的问题,但在Python中,你以python的方式做事 . 它's not a '为什么' question. It'那里你可以用 x+= 做同样的事情 . 在The Zen of Python中,它给出了:"there should only be one way to solve a problem."多种选择在艺术(表达自由)方面很棒,但在工程方面却很糟糕 .
18 回答
这不是因为它没有意义;将“x”定义为“x = 1,评估x的先前绑定”是完全合理的 .
如果你想知道最初的原因,你必须要么通过旧的Python邮件列表或者询问那里的人(例如Guido),但事实很容易证明:
简单的增量和减量都不经常在Python中像
for(int i = 0; i < 10; ++i)
那样写东西 . 相反,你做的事情像for i in range(0, 10)
.因为's not needed nearly as often, there'没有理由给它自己特殊的语法;当你需要增加时,
+=
通常就好了 .它是否值得添加到该语言的核心语法的问题 . 请记住,这是四个运算符 - postinc,postdec,preinc,predec,并且每个运算符都需要有自己的类重载;它们都需要指定和测试;它会在语言中添加操作码(暗示一个更大的,因此更慢的VM引擎);每个支持逻辑增量的类都需要实现它们(在
+=
和-=
之上) .这对于
+=
和-=
都是多余的,因此它将成为净损失 .This original answer I wrote is a myth from the folklore of computing :Dennis Ritchie将其揭穿为"historically impossible",如2012年7月ACM通讯编辑的信中所述doi:10.1145/2209249.2209251
C增量/减量运算符是在C编译器不是非常智能的时候发明的,并且作者希望能够指定应该使用机器语言运算符的直接意图,这为编译器保存了一些循环 . 可能会做一个
代替
PDP-11甚至支持分别对应于
*++p
和*p++
的"autoincrement"和"autoincrement deferred"指令 . 如果非常好奇,请参见the manual的第5.3节 .由于编译器足够聪明,可以处理C语法中内置的高级优化技巧,因此它们现在只是语法上的便利 .
Python没有把意图传达给汇编程序的技巧,因为它没有使用它 .
我一直认为它与python的这一行有关:
x和x = 1完全相同,所以没有理由同时使用两者 .
当然,我们可以说“Guido刚刚决定了这种方式”,但我认为问题实际上是关于这个决定的原因 . 我认为有几个原因:
它将语句和表达混合在一起,这不是一个好习惯 . 见http://norvig.com/python-iaq.html
它通常鼓励人们编写不太可读的代码
语言实现的额外复杂性,如上所述,这在Python中是不必要的
因为,在Python中,整数是不可变的(int's =实际上返回一个不同的对象) .
此外,使用/ - 您需要担心前后增量/减量,并且只需要再按一次键击
x+=1
. 换句话说,它以非常小的收益为代价避免了潜在的混淆 .要在该页面上完成已经很好的答案:
让我们假设我们决定这样做,前缀(
++i
)会破坏一元和 - 运算符 .今天,前缀为
++
或--
什么都不做,因为它使一元加运算符两次(什么都不做)或一元减去两次(两次:取消自身)所以这可能会打破这种逻辑 .
清晰度!
Python很多关于 clarity 并且没有程序员可能正确地猜测
--a
的含义,除非他/他学会了具有该构造的语言 .Python也是很多关于 avoiding constructs that invite mistakes 的,并且
++
运算符是众所周知的丰富缺陷来源 . 这两个原因足以让Python中没有这些运算符 .Python使用缩进来标记块而不是语法手段(例如某种形式的开始/结束包围或强制结束标记)的决定主要基于相同的考虑因素 .
为了说明,请在2005年查看 discussion around introducing a conditional operator (在C:
cond ? resultif : resultelse
中)到Python中 . 至少读取first message和decision message的discussion(之前在同一主题上有几个前兆) .Trivia: 其中经常提到的PEP是"Python Extension Proposal" PEP 308 . LC意味着list comprehension,GE意味着generator expression(如果那些让你困惑的话,不要担心,它们不是Python的少数复杂点) .
它就是这样设计的 . 增量和减量运算符只是
x = x + 1
的捷径 . Python通常采用一种设计策略,减少了执行操作的替代方法的数量 . Augmented assignment是最接近Python中递增/递减运算符的东西,它们甚至在Python 2.0之前都没有添加 .我'm very new to python but I suspect the reason is because of the emphasis between mutable and immutable objects within the language. Now, I know that x++ can easily be interpreted as x = x + 1, but it LOOKS like you'就地增加一个可以是不可变的对象 .
只是我的猜测/感觉/预感 .
我对python没有
++
运算符的理解如下:当你在pythona=b=c=1
中写这个时,你会得到三个指向同一个对象的变量(标签)(值为1) . 您可以使用id函数验证这一点,该函数将返回一个对象内存地址:所有三个变量(标签)都指向到同一个对象 . 现在增加一个变量并查看它如何影响内存地址:
您可以看到变量
a
现在指向另一个对象作为变量b
和c
. 因为你已经使用了a = a + 1
,所以它是明确的 . 换句话说,您完全指定另一个对象来标记a
. 想象一下,你可以写a++
它会建议你没有分配给变量a
new对象但是ratter增加旧对象 . 所有这些东西都是恕我直言,以尽量减少混乱 . 为了更好地理解python变量的工作原理:In Python, why can a function modify some arguments as perceived by the caller, but not others?
Is Python call-by-value or call-by-reference? Neither.
Does Python pass by value, or by reference?
Is Python pass-by-reference or pass-by-value?
Python: How do I pass a variable by reference?
Understanding Python variables and Memory Management
Emulating pass-by-value behaviour in python
Python functions call by reference
Code Like a Pythonista: Idiomatic Python
我认为它源于Python信条“明确比隐含更好” .
首先,Python只受C的间接影响;它受ABC的影响很大,apparently does not have these operators,所以不要在Python中找到它们也不会有任何意外 .
其次,正如其他人所说,增量和减量已经由
+=
和-=
支持 .第三,对
++
和--
运算符集的完全支持通常包括支持它们的前缀和后缀版本 . 在C和C中,这可能导致各种各样的"lovely"构造(对我而言)违背Python所包含的简单性和直接性的精神 .例如,虽然C语句
while(*t++ = *s++);
对于有经验的程序员来说可能看起来简单而优雅,但对于学习它的人来说,它只是简单而已 . 抛出前缀和后缀增量和减量的混合,甚至许多专业人员将不得不停下来思考一下 .这可能是因为@GlennMaynard正在考虑与其他语言相比较的问题,但在Python中,你以python的方式做事 . 它's not a '为什么' question. It'那里你可以用
x+=
做同样的事情 . 在The Zen of Python中,它给出了:"there should only be one way to solve a problem."多种选择在艺术(表达自由)方面很棒,但在工程方面却很糟糕 .正如我所理解的那样你不会认为记忆中的 Value 会发生变化 . 在c中,当你执行x时,内存中x的值会发生变化 . 但是在python中所有数字都是不可变的,因此x指向的地址仍然是x而不是x 1.当你写x时你会认为x改变真正发生的是x refrence改变到内存中存储x 1的位置如果母校不存在,则重新创建此位置 .
++
类运算符是具有副作用的表达式 . 这是Python中通常没有的东西 .出于同样的原因,赋值不是Python中的表达式,因此阻止了常见的
if (a = f(...)) { /* using a here */ }
惯用法 .最后我怀疑运算符与Pythons引用语义不一致 . 请记住,Python没有带有C / C语义的变量(或指针) .
也许更好的问题是问为什么C中存在这些运算符.K&R调用递增和递减运算符'异常'(第2.8节第46页) . 引言称它们“更简洁,效率更高” . 我怀疑这些操作总是出现在指针操作中的事实也在它们的介绍中发挥了作用 . 在Python中,可能已经决定尝试优化增量是没有意义的(实际上我只是在C中进行了测试,似乎gcc生成的程序集在两种情况下都使用addl而不是incl)并且没有指针算术;所以它应该只是一种方式去做,我们知道Python厌恶这一点 .
我认为这涉及对象的可变性和不变性的概念 . 2,3,4,5在python中是不可变的 . 请参阅下图 . 2具有固定的id直到这个python进程 .
x本质上意味着像C一样的就地增量 . 在C中,x执行就地增量 . 因此,x = 3,x将在内存中增加3到4,这与python不同,其中3仍然存在于内存中 .
因此在python中,您不需要在内存中重新创建值 . 这可能会导致性能优化 .
这是一个基于预感的答案 .
运算符与=运算符不完全相同 . 实际上两者的结果是相同的,但使用有一些区别 . 例如,您可以在三元条件,for循环等中使用运算符但不能使用= . 在底部,我们感到需要和 - ,出于这个原因 .