Answers:
不是因为它没有道理;而是因为它没有意义。最好将“ x ++”定义为“ x + = 1,求出x的先前绑定”。
如果您想知道最初的原因,则必须要么浏览旧的Python邮件列表,要么询问那里的某个人(例如Guido),但是在事实成立之后就很容易找到理由了:
与其他语言一样,不需要简单的增量和减量。您不会for(int i = 0; i < 10; ++i)
经常用Python 编写东西。相反,你做类似的事情for i in range(0, 10)
。
由于几乎不需要它,因此没有太多理由为其提供特殊的语法。当您确实需要增加时,+=
通常就可以了。
这不是是否有意义,还是可以做到的决定。这是一个好处是否值得添加到该语言的核心语法中的问题。请记住,这是四个运算符-postinc,postdec,preinc,predec,并且每个运算符都需要具有自己的类重载;他们都需要指定和测试;它将在语言中添加操作码(暗示更大,因此更慢的VM引擎);每个支持逻辑增量的类都需要实现它们(在+=
和之上-=
)。
+=
和都是多余的-=
,因此将成为净亏损。
i
直接循环-如果您确实需要它,而不能仅仅使用它array.append()
i++
和++i
...
++
并--
以导致未定义或未指定的方式使用行为。它们使编写复杂的,难以正确解析的代码成为可能。
我写的这个原始答案是关于计算机民俗的一个神话:被丹尼斯·里奇(Dennis Ritchie)认为是“历史上不可能的”,正如ACM通讯编辑在2012年7月致函doi:10.1145 / 2209249.2209251
C增/减运算符是在C编译器不是很聪明的时候发明的,作者希望能够指定使用机器语言运算符的直接意图,从而节省了编译器的几个周期,可能会做一个
load memory
load 1
add
store memory
代替
inc memory
PDP-11甚至支持分别对应于*++p
和的“自动递增”和“延迟自动递增”指令*p++
。如果非常好奇,请参阅手册第5.3节。
由于编译器足够聪明,可以处理C语法中内置的高级优化技巧,因此它们现在只是语法上的便利。
Python没有技巧来向汇编器传达意图,因为它不使用汇编器。
我一直以为这与python禅的这一行有关:
应该有一种(最好只有一种)明显的方式来做到这一点。
x ++和x + = 1做完全相同的事情,因此没有理由同时使用两者。
one--
是零吗?
one--
在句子中为1,但之后立即为零。因此,这种“ koan”也暗示增量/减量运算符不是显而易见的。
当然,我们可以说“圭多岛就是这样决定的”,但我认为问题实际上是做出该决定的原因。我认为有以下几个原因:
因为在Python中,整数是不可变的(int的+ =实际上返回了一个不同的对象)。
同样,使用++ /-时,您需要担心增量前后的递增和递减,并且只需要再写一次按键即可x+=1
。换句话说,它避免了潜在的混乱,但付出的代价却很小。
42++
...的代码…… 在某些旧的Fortran编译器中(实际上我已经读过)实际上可能是这样的(修改文字常量):将来的所有使用那么,该程序运行中的文字的确会具有不同的值。调试愉快!
int
通常是不可变的。int
C中的in只是指定内存中的位置。而且那个地方的位子非常可变。例如,您可以创建的引用int
并更改该引用的引用。此更改在int
对该位置的所有引用(包括原始变量)中均可见。对于Python整数对象,这并不适用。
Python有很多关于清晰度--a
的知识,除非他/她学习了具有这种构造的语言,否则任何程序员都不可能正确地猜测的含义。
Python还有很多关于避免引发错误的构造的知识,并且++
已知运算符是缺陷的丰富来源。这两个原因足以在Python中没有这些运算符。
Python使用缩进来标记块而不是诸如某种形式的开始/结束方括号或强制结束标记之类的句法手段的决定很大程度上基于相同的考虑。
作为说明,请看一下有关在2005年向Python中引入条件运算符(在C:中cond ? resultif : resultelse
)的讨论。至少请阅读该讨论的第一条消息和决策消息(之前有相同主题的多个先驱)。
琐事: 其中经常提到的PEP是“ Python扩展建议” PEP 308。LC表示列表理解,GE表示生成器表达式(不要担心,如果它们使您感到困惑,它们不是Python的少数复杂地方)。
我对python为什么没有++
运算符的理解如下:当您在python中编写此代码时,a=b=c=1
您将获得三个变量(标签),它们指向同一对象(值为1)。您可以使用id函数进行验证,该函数将返回对象内存地址:
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
它,所以它很明显。换句话说,您将另一个对象完全分配给label a
。想象一下,您可以编写a++
它,这表明您没有分配给变量a
新对象,而是增加了旧对象的数量。所有这些东西都是恕我直言,以尽量减少混乱。为了更好地理解,请参见python变量如何工作:
我是python的新手,但我怀疑原因是由于该语言中的可变对象和不可变对象之间的强调。现在,我知道x ++可以很容易地解释为x = x + 1,但是它看起来就像您就地递增一个不可变的对象一样。
只是我的猜测/感觉/预感。
x++
更加接近。x += 1
x = x + 1
首先,Python仅受C间接影响。它在很大程度上受到影响ABC,这显然不具备这些运营商,所以它不应该有任何巨大的惊喜不会找到它们在Python两种。
其次,正如其他人所说,递增和递减由支持+=
和-=
了。
第三,对++
and --
运算符集的完全支持通常包括同时支持它们的前缀和后缀版本。在C和C ++中,这可能导致各种“可爱”的构造(在我看来)与Python所包含的简单性和直截了当的精神背道而驰。
例如,尽管C语句while(*t++ = *s++);
对于有经验的程序员而言似乎简单而优雅,但对于学习它的人来说,却绝非简单。混合使用前缀和后缀增量和减量,甚至许多专业人士也必须停下来思考一下。
我认为这源于Python的信条,即“明确胜于隐含”。
这可能是因为@GlennMaynard正在将问题与其他语言进行比较,但是在Python中,您是以python方式进行操作的。这不是一个“为什么”的问题。在那里,您可以使用达到相同的效果x+=
。在《 Python的禅宗》中,给出了:“只有一种解决问题的方法。” 多种选择在艺术上(表达自由)很棒,但在工程上却很糟糕。
++
运算符的类别是具有副作用的表达式。这是Python中通常找不到的东西。
出于同样的原因,赋值不是Python中的表达式,因此防止了通用 if (a = f(...)) { /* using a here */ }
用法。
最后,我怀疑操作符与Python的参考语义不是很一致。请记住,Python没有具有C / C ++已知语义的变量(或指针)。
f(a)
哪里a
是列表,一些不可变的对象。
也许更好的问题是问为什么这些运算符存在于C中。K&R调用增量和减量运算符为“异常”(第2.8页第2.8节)。导言称它们“更简洁,通常更高效”。我怀疑这些操作总是在指针操作中出现的事实也影响了它们的引入。在Python中,可能已经决定尝试优化增量没有任何意义(事实上,我只是在C中进行了测试,而且似乎gcc生成的程序集在两种情况下都使用addl而不是incl),并且没有指针算法;因此,它本来只是另一种实现方式,而我们知道Python不愿这样做。
要在该页面上完成已经很好的答案:
假设我们决定这样做,在前缀(++i
)处打乱一元+和-运算符。
今天,以++
或--
做任何前缀都没有,因为它使一元加号运算符两次(不执行任何操作)或一元减号两次(两次:取消自身)成为可能
>>> i=12
>>> ++i
12
>>> --i
12
这样可能会破坏这种逻辑。
我认为这涉及对象的可变性和不可变性的概念。2,3,4,5在python中是不可变的。请参考下图。2具有固定的ID,直到此python进程为止。
x ++本质上意味着像C的就地增量。在C中,x ++执行就地增量。因此,x = 3,并且x ++会将内存中的3增加到4,这与python中内存中仍然存在3的情况不同。
因此,在python中,您无需在内存中重新创建值。这可能会导致性能优化。
这是基于预感的答案。
我知道这是一个旧线程,但是没有涵盖++ i的最常见用例,即在没有提供索引的情况下手动索引集。这就是为什么python提供enumerate()的原因
示例:在任何给定的语言中,当您使用诸如foreach之类的结构来遍历一个集合时,出于示例的考虑,我们甚至会说它是无序的集合,并且您需要一个唯一的索引来区分所有内容,例如
i = 0
stuff = {'a': 'b', 'c': 'd', 'e': 'f'}
uniquestuff = {}
for key, val in stuff.items() :
uniquestuff[key] = '{0}{1}'.format(val, i)
i += 1
在这种情况下,python提供了一个枚举方法,例如
for i, (key, val) in enumerate(stuff.items()) :