在Python中,+=运算符返回的是两个操作数相加后的值。

16 浏览
0 Comments

在Python中,+=运算符返回的是两个操作数相加后的值。

当我试图回答stackoverflow上关于Python中“=”和“+=”的区别的另一个人的问题时,我遇到了以下问题:\n

class Foo:
    def __init__(self, value, name="default"):
        self.value = value
        self.name = name
    def __add__(self, that):
        return Foo(self.value + that.value)
    def __iadd__(self, that):
        self.value = self.value + that.value
        return self
    def __str__(self):
        return "name: {}, value: {:d}".format(self.name, self.value)
a = Foo(1, 'alice')
b = Foo(2, 'bob')
print(a+=b)

\n最后的`print`调用不成功,并给出以下错误:\n

File "", line 3
    print(a+=b)
            ^
SyntaxError: invalid syntax

\n我不知道为什么这个不起作用。也许与关键字参数传递机制有关?我只是找不到关于这个主题的任何资源,因为重载的`__iadd__`方法已经返回一个`Foo`对象。\n************** 更新 ******************\n如果我像这样修改`__iadd__`方法(只移除`return`语句):\n

...
    def __iadd__(self, that):
        print("__iadd__ was called")
        self.value = self.value + that.value
a = Foo(1, 'alice')
b = Foo(2, 'bob')
a += b
print(a)  # 输出:None

\n所以,`__iadd__`中的最后一个`return`语句确实是必需的。但它不像我想的那样起作用(我来自C/C++背景,所以这种行为对我来说有点奇怪)\n************************* 第二次更新 ********************************\n我几乎忘记了在Python中,`=`构成了一个语句而不是一个表达式。`__iadd__`中的`return`语句和我在其他语言中的经验使我产生了一种错觉,即`+=`可以用作表达式。\n如Python文档所述,`__add__`用于构造一个新对象。`__iadd__`用于原地修改。但这完全取决于实现。尽管`__iadd__`返回一个对象,但该对象在某种程度上被语言“拦截”并重新分配给左操作数,最终效果是,`__iadd__`仍然是一个语句,而不是一个表达式。如果我理解错了,请纠正我。此外,我没有找到任何证实`+=`是一个语句的资源。\n

总结

\n

    \n

  1. 一个简单的代码,比如`a = 1`是一个赋值语句。它不能用作函数参数。但是,关键字参数传递没有受到此限制:`print(\'Hello world\', end=\'\')`仍然有效。
  2. \n

  3. \n
      \n

    • `x = x + y`等同于`x = x.__add__(y)`,
    • \n

    • `x += y`等同于`x = x.__iadd__(y)`,详细信息请查看文档。
    • \n

    \n

  4. \n

  5. 一个例子:
  6. \n

\n

class Foo:
    def __init__(self, value, name="default"):
        self.value = value
        self.name = name
    def __add__(self, that):
        return Foo(self.value + that.value)
    def __iadd__(self, that):
        self.value = self.value + that.value
        return self
    def __str__(self):
        return "name: {}, value: {:d}".format(self.name, self.value)
a = Foo(1, 'alice')
b = Foo(2, 'bob')
c = a + b # 对象a和b不变
a += b    # 对象a被修改
print(c) # 输出:name: default, value: 3
print(a) # 输出:name: alice, value: 3

0
0 Comments

这是一个语法错误,是因为将赋值语句用作表达式。这里有另一个Stack Overflow的帖子,解释了语句和表达式之间的差异。

这不是运算符重载实现的错误。

在另一个上下文中,这个语法错误的示例(使用int而不是Foo):

a = 2
b = 3
# 仍然是个错误!
print(a += b) # 使用标准int += 运算符时出错

如何修复语法问题:

a = 2
b = 3
a += b      # 将赋值语句分开...
print(a)    #     ...并给print函数一个表达式

这与运算符有关。运算符使这行成为一个语句(即“不可打印的”)。

感谢指出我的措辞不明确。我更新了我的帖子,澄清了这个错误不是源自实现,而是源自它的使用方式。

0
0 Comments

Python中的运算符+=返回的是什么?这个问题的出现是因为Python的语义可能会让事情变得混乱。为了举例说明,可以尝试通过以下示例进行演示:

class Foo:
    def __init__(self, value):
        self.value = value
    def __iadd__(self, other):
        self.value = self.value + other.value
        return 'did iadd'
a = Foo(1)
c = a
c += Foo(2)
print((c, a.value))

应该得到打印出`('did iadd', 3)`。

根据文档:

x += y 相当于 x = x.__iadd__(y)

`__iadd__`的约定是你应该以这样的方式实现它,使得`x = x + y`的语义与`x += y`的语义“相同”。"相同"取决于问题的细节,例如对于不可变对象(例如整数或字符串),这将需要分配一个新对象并更新引用以指向新对象,例如:

a = 500  # move out of the "interned" number space
c = a
a += 1
print(id(a), id(c))

应该给出两个不同的数字,在CPython中它们将是两个不同的地址,都是独立且不可变的int对象。对于其他数据类型,允许进行可变/原地更新可能是有用的,例如为了提高效率或其他原因。`__iadd__`的语义允许类的实现选择一个默认值。

每种语言都有其独特之处,因此建议不要试图与C++进行太直接的比较。特别是因为C++有很多历史包袱被迫携带。

的确,`x += y`与`x = x.__iadd__(y)`是相同的。最“流行”的答案表明`x += y`与`x = x + y`相同是令人困惑的,因为`x += y`调用`__iadd__`而`x = x + y`调用`__add__`,两者都跟随一个赋值操作。我现在认为这一点非常清楚了。谢谢!

0
0 Comments

在Python中,运算符+=用于将右侧的值添加到左侧的变量,并将结果赋给左侧的变量。然而,这个操作符返回的值与其他语言中的操作符不同。在Python中,+=操作符返回的是被赋值后的变量的引用,并不是赋值的结果。

这种设计是有原因的。其中一个原因是为了避免类似于C语言中的经典错误。在C语言中,如果将赋值操作符"="误写成"==",就会导致条件判断出错。例如,如果写成if (a=b),实际上用户可能想要测试的是a==b,但实际上会将b赋给a。为了避免这种常见的错误,Python中的赋值操作符不返回赋值的结果。

然而,Python 3.8引入了一种新的赋值方法,称为赋值表达式。赋值表达式允许将赋值的结果作为参数传递,这在列表推导中非常方便。虽然不能直接进行原地相加的操作,但可以先进行相加,然后再赋值。

例如,在Python 3.8中,可以这样使用赋值表达式:

a = 2

b = 3

print(a := a + b)

输出结果为5。在这个例子中,a先与b相加得到结果5,然后将结果赋给a,并将结果打印出来。

总结起来,Python中的+=操作符返回的是被赋值后的变量的引用,并不是赋值的结果。这种设计是为了避免常见的赋值错误。然而,Python 3.8引入了赋值表达式,可以方便地将赋值的结果作为参数传递。虽然不能直接进行原地相加的操作,但可以先进行相加,然后再赋值。这种新的赋值方法为Python的使用带来了更多的灵活性和便利性。

0