我注意到可以将预增/减运算符应用于变量(例如++count )。 它可以编译,但实际上并不会改变变量的值!

Python中预增/减运算符(++ /-)的行为是什么?

为什么Python会偏离C / C ++中看到的这些运算符的行为?


#1楼

尽管其他答案在显示仅仅+意义上是正确的(即,保留数字,如果是1),则是正确的,但就其不解释会发生什么而言,它们是不完整的。

确切地说, +x值为x.__pos__()++x值为x.__pos__().__pos__()

我可以想象一个非常奇怪的类结构(孩子们,不要在家做!),像这样:

class ValueKeeper(object):def __init__(self, value): self.value = valuedef __str__(self): return str(self.value)class A(ValueKeeper):def __pos__(self):print 'called A.__pos__'return B(self.value - 3)class B(ValueKeeper):def __pos__(self):print 'called B.__pos__'return A(self.value + 19)x = A(430)
print x, type(x)
print +x, type(+x)
print ++x, type(++x)
print +++x, type(+++x)

#2楼

++不是运算符。 它是两个+运算符。 +运算符是身份运算符,不执行任何操作。 (澄清: +-一元运算符仅对数字有效,但我想您不会期望假设的++运算符对字符串有效。)

++count

解析为

+(+count)

转化为

count

您必须使用稍长的+=运算符来完成您想做的事情:

count += 1

我怀疑++--运算符由于一致性和简单性而被遗漏了。 我不知道Guido van Rossum做出决定的确切论据,但我可以想象一些论点:

  • 更简单的解析。 从技术上讲,解析++count是模棱两可的,因为它可能是++count (两个一元+运算符),就像它可能是++count (一个一元++运算符)一样容易。 它不是语法上的明显歧义,但确实存在。
  • 语言更简单。 ++只是+= 1的同义词。 这是一种速记的发明,因为C编译器很愚蠢,并且不知道如何将a += 1优化a += 1大多数计算机拥有的inc指令。 在优化编译器和字节码解释语言的这一天,通常不赞成在一种语言中添加运算符以允许程序员优化其代码,尤其是在像Python这样设计成一致且易读的语言中。
  • 令人困惑的副作用。 使用++运算符的语言中一个常见的新手错误是混合使用递增/递减运算符之间的差异(优先级和返回值),Python喜欢消除语言“陷阱”。 C中的预增/后增的优先级问题非常棘手,难以置信。

#3楼

当您想增加或减少时,通常需要对整数进行操作。 像这样:

b++

但是在Python中,整数是不可变的 。 那是你不能改变他们。 这是因为可以使用多个名称使用整数对象。 尝试这个:

>>> b = 5
>>> a = 5
>>> id(a)
162334512
>>> id(b)
162334512
>>> a is b
True

上面的a和b实际上是同一对象。 如果增加a,也将增加b。 那不是你想要的。 因此,您必须重新分配。 像这样:

b = b + 1

或更简单:

b += 1

它将b重新分配给b+1 。 那不是增量运算符,因为它不会增量b ,而是对其进行重新分配。

简而言之:Python在这里的行为有所不同,因为它不是C,也不是机器代码的底层包装,而是一种高级动态语言,在这种语言中,增量没有意义,也没有C所必需,例如,每次有循环时在哪里使用它们。


#4楼

Python没有这些运算符,但是如果您确实需要它们,可以编写具有相同功能的函数。

def PreIncrement(name, local={}):#Equivalent to ++nameif name in local:local[name]+=1return local[name]globals()[name]+=1return globals()[name]def PostIncrement(name, local={}):#Equivalent to name++if name in local:local[name]+=1return local[name]-1globals()[name]+=1return globals()[name]-1

用法:

x = 1
y = PreIncrement('x') #y and x are both 2
a = 1
b = PostIncrement('a') #b is 1 and a is 2

如果要更改局部变量,则必须在函数内部添加locals()作为第二个参数,否则它将尝试更改全局变量。

x = 1
def test():x = 10y = PreIncrement('x') #y will be 2, local x will be still 10 and global x will be changed to 2z = PreIncrement('x', locals()) #z will be 11, local x will be 11 and global x will be unaltered
test()

使用这些功能,您还可以执行以下操作:

x = 1
print(PreIncrement('x'))   #print(x+=1) is illegal!

但是我认为以下方法更加清晰:

x = 1
x+=1
print(x)

减量运算符:

def PreDecrement(name, local={}):#Equivalent to --nameif name in local:local[name]-=1return local[name]globals()[name]-=1return globals()[name]def PostDecrement(name, local={}):#Equivalent to name--if name in local:local[name]-=1return local[name]+1globals()[name]-=1return globals()[name]+1

我在将javascript转换为python的模块中使用了这些功能。


#5楼

是的,我也错过了++和-功能。 几百万行c代码使这种思想深深地扎根在我的脑海中,而不是与之抗争……这是我拼凑而成的一类,实现了:

pre- and post-increment, pre- and post-decrement, addition,
subtraction, multiplication, division, results assignable
as integer, printable, settable.

这是:

class counter(object):def __init__(self,v=0):self.set(v)def preinc(self):self.v += 1return self.vdef predec(self):self.v -= 1return self.vdef postinc(self):self.v += 1return self.v - 1def postdec(self):self.v -= 1return self.v + 1def __add__(self,addend):return self.v + addenddef __sub__(self,subtrahend):return self.v - subtrahenddef __mul__(self,multiplier):return self.v * multiplierdef __div__(self,divisor):return self.v / divisordef __getitem__(self):return self.vdef __str__(self):return str(self.v)def set(self,v):if type(v) != int:v = 0self.v = v

您可以这样使用它:

c = counter()                          # defaults to zero
for listItem in myList:                # imaginary taskdoSomething(c.postinc(),listItem) # passes c, but becomes c+1

...已经有了c,您可以执行此操作...

c.set(11)
while c.predec() > 0:print c

....要不就...

d = counter(11)
while d.predec() > 0:print d

...并用于(重新)分配为整数...

c = counter(100)
d = c + 223 # assignment as integer
c = c + 223 # re-assignment as integer
print type(c),c # <type 'int'> 323

...这将使c保持为类型计数器:

c = counter(100)
c.set(c + 223)
print type(c),c # <class '__main__.counter'> 323

编辑:

然后还有一些意想不到的(并且完全是不想要的)行为

c = counter(42)
s = '%s: %d' % ('Expecting 42',c) # but getting non-numeric exception
print s

...因为在该元组中,没有使用getitem (),而是将对对象的引用传递给格式函数。 叹。 所以:

c = counter(42)
s = '%s: %d' % ('Expecting 42',c.v) # and getting 42.
print s

…或更确切地说,是我们实际上想要发生的事情,尽管详细程度以实际形式相反(使用cv )…

c = counter(42)
s = '%s: %d' % ('Expecting 42',c.__getitem__()) # and getting 42.
print s

#6楼

TL; DR

Python没有一元增减运算符( -- / ++ )。 相反,要增加值,请使用

a += 1

更多细节和陷阱

但是请注意这里。 如果您来自C,即使在python中也是如此。 Python没有C的意义上的“变量”,而是python使用名称对象 ,并且int是不可变的。

所以说你做

a = 1

这在python中的含义是:创建一个值为1 int类型的对象,并将名称a绑定到该对象。 该对象是具有值1int的实例, 名称 a引用了它。 名称a和它所引用的对象是不同的。

现在说你做

a += 1

由于int是不可变的,因此这里发生的情况如下:

  1. 查找a引用的对象(它是ID为0x559239eeb380int
  2. 查找对象0x559239eeb380的值(它是1
  3. 给该值加1(1 +1 = 2)
  4. 创建一个值为2 int对象(其对象ID为0x559239eeb3a0
  5. 将名称a重新绑定到这个新对象
  6. 现在, a引用对象0x559239eeb3a0 ,而原始对象( 0x559239eeb380 )不再用名称a 0x559239eeb380 。 如果没有其他名称引用原始对象,则稍后将对其进行垃圾回收。

自己尝试一下:

a = 1
print(hex(id(a)))
a += 1
print(hex(id(a)))

#7楼

在Python中,与Common Lisp,Scheme或Ruby之类的语言相比,严格执行了表达式和语句之间的区别。

维基百科

因此,通过引入此类运算符,可以打破表达式/语句的拆分。

出于同样的原因,你不能写

if x = 0:y = 1

就像其他一些语言一样,这种语言没有保留。

Python中递增和递减运算符的行为相关推荐

  1. python中数字逐个递增_Python中递增和递减运算符的行为

    不是运算符.它是两个运算符.运算符是身份运算符,它什么也不做. (澄清:一元运算符只用于数字,但我假设你不会期望一个假设的操作符在字符串上工作.) ++count 解析为 +(+count) 翻译成 ...

  2. java递减_关于Java中递增和递减运算符的有趣事实

    关于Java中的递增和递减运算符,有许多有趣的事实.我们将通过示例讨论其中的一些-增量和减量运算符不能与'final'变量一起使用.这是由于与'final'关键字相关联的变量无法更改的事实- 示例pu ...

  3. 重载运算与类型转换——基本概念,输入和输出运算符,算术和关系运算符,赋值运算符,下标运算符,递增和递减运算符,成员访问运算符...

    一.基本概念 重载的运算符时具有特殊名字的函数:它们的名字由关键字operator和其后要定义的运算符号共同组成.和其他函数一样,重载的运算符也包含返回类型.参数列表以及函数体. 重载运算符函数的参数 ...

  4. C++primer 第 4 章 表达式 4.1基础 4 . 2 算术运算符 4 .3 逻辑和关系运算符 4 . 4 赋值运算符 4 .5 递增和递减运算符 4.6成员访问运算符

    表达式由一个或多个运算对象(operand)组成,对表达式求值将得到一个结果(result) 字面值和变量是最简单的表达式(expression),其结果就是字面值和变量的值.把一个运算符(opera ...

  5. JavaScript递增和递减运算符

    JavaScript前文回顾: 认识JavaScript到初体验 JavaScript 注释以及输入输出语句 JavaScript变量的使用.语法扩展.命名规范 JavaScript数据类型简介以及简 ...

  6. java递减_浅谈java的自动递增和递减运算符的使用方法_java运算符_java_课课家

    和C类似,java提供了丰富的快捷运算方式.这些快捷运算可使代码更清爽,更易录入,也更易读者辨读. 两种很不错的快捷运算方式是递增和递减运算符(常称作"自动递增"和"自动 ...

  7. PHP的递增递减运算符有哪些,递增/递减运算符

    PHP 支持 C 风格的前/后递增与递减运算符. Note: 递增/递减运算符不影响布尔值.递减 NULL 值也没有效果,但是递增 NULL 的结果是 1. ### 递增/递减运算符 | 例子 | 名 ...

  8. C++ 语言递增和递减运算符

    C++ 语言递增和递减运算符 递增运算符 ++ 和递减运算符 -- 为对象的加 1 和减 1 操作提供了一种简洁的书写形式.这两个运算符还可应用于迭代器,很多迭代器本身不支持算术运算,此时递增和递减运 ...

  9. JavaScript系列之递增和递减运算符

    文章の目录 1.概述 2.自增(++) 2.1.概述 2.2.语法 2.3.分类 2.3.1.前置递增运算符 2.3.2.后置递增运算符 3.自减(--) 3.1.概述 3.2.语法 3.3.分类 3 ...

最新文章

  1. 2021年大数据Spark(五十三):Structured Streaming Deduplication
  2. Asp.Net 使用 GDI+ 绘制3D饼图入门篇源码
  3. 生活有时会有点苦涩——一位第六年还没发paper的PHD的自述
  4. 咏南CS插件开发框架也可BS方式部署
  5. Linux下的几款svn gui工具
  6. 中国人民银行:关于防范代币发行融资风险的公告
  7. matlab m语言,我要编写matlab一个公式的m语言,请问错在哪里?,M语言的MATLAB的M语言...
  8. AQS.accquire
  9. Exchange 2010 RPC配置静态RPC端口客户端访问、通讯簿服务和公用文件夹连接
  10. 中国无人车第一案剧情突变:景驰投入百度Apollo怀抱,下周或和解收场
  11. 手机软件Toast无法显示提示信息
  12. python怎么修改列名_PYTHON:更改列名
  13. nginx+uWSGI+django+virtualenv+supervisor发布web服务器流程
  14. 黄金矿工java实现
  15. 应急响应-linux-webshell查查杀工具:河马webshell查杀和深信服Webshell
  16. word研究报告排版要领
  17. 爬壁机器人外文文献_仿生爬壁机器人的研究现状
  18. 软件测试实习生(3k)
  19. web测试与APP测试方法总结
  20. 北京小客车摇号数据的一点质疑

热门文章

  1. 【剑指offer-Java版】17合并两个排序链表
  2. Code Push 热更新使用详细说明和教程
  3. Git使用教程之本地仓库的基本操作
  4. python发送文件到邮箱_python发送文件夹内容到邮箱
  5. python主要学哪些课程_Python学习课程大纲自学Python参考
  6. (0074)iOS开发之UITableView的优化
  7. swift_015(Swift 的函数)
  8. ftrace跟踪内核_ftrace、kpatch、systemtap的基本原理、联系和区别
  9. DO YOU WANNA BUILD A SNOW MAN ?
  10. MYSQL WHERE语句