首页 > 解决方案 > 为什么 'x = x + something' 不返回与 'x += something' 相同的结果?

问题描述

我正在尝试创建一个函数sprout_leaves,该函数会在原始树 t 中的每个叶子处生成新叶子,其中包含叶子中的数据并返回结果树。

所以,输出会是这样的

>>> t1 = tree(1, [tree(2), tree(3)])
>>> print_tree(t1)
1
  2
  3
>>> new1 = sprout_leaves(t1, [4, 5])
>>> print_tree(new1)
1
  2
    4
    5
  3
    4
    5

>>> t2 = tree(1, [tree(2, [tree(3)])])
>>> print_tree(t2)
1
  2
    3
>>> new2 = sprout_leaves(t2, [6, 1, 2])
>>> print_tree(new2)
1
  2
    3
      6
      1
      2

现在我的函数看起来像这样:

def sprout_leaves(t, leaves):

    leaves_as_tree = branches(tree('', [tree(x) for x in leaves]))


    if not is_leaf(t):
    
        for b in branches(t):
            if is_leaf(b):
                b += leaves_as_tree  # !!! 
            else:
                return tree(label(t),[(sprout_leaves(tree(label(b), branches(b)), leaves))])
    return t

此函数为我返回所需的结果:

>>> t1 = tree(1, [tree(2), tree(3)])
>>> new1 = sprout_leaves(t1, [4, 5])
>>> print_tree(new1)
1
  2
    4
    5
  3
    4
    5

但是,如果我更改b += leave_as_treeb = b + leaves_as_tree,则输出更改为:

>>> t1 = tree(1, [tree(2), tree(3)])
>>> new1 = sprout_leaves(t1, [4, 5])
>>> print_tree(new1)
1
  2
  3

我的问题很简单:为什么会这样?无论我尝试什么,如果我不使用+=,输出都会出错。

要重现此示例,以下是所需的功能:

https://codeshare.io/adqo6M

标签: pythonpython-3.x

解决方案


b = b + leaves_as_tree做了几件事:

  • 来电b.__add__(leaves_as_tree)
  • 将该操作的结果分配给 name b。现在b指向与以前不同的对象。

b += leaves_as_tree是不同的:

  • 它调用b.__iadd__(leaves_as_tree)
  • ……就是这样。

所以真正的区别是b = b + leaves_as_tree创建一个新对象然后更新b指向它,但b += leaves_as_tree调用一个函数来改变 b 到位。

object.__iadd__(注意:必须在适当的位置改变对象并没有什么神奇的,但是如果某个类将其定义为做一些不同的事情,那么每个人都会对该类的作者感到恼火。)

list这是使用内置类的示例:

>>> a = []
>>> id(a)
4315491720

>>> a += [1, 2, 3]
>>> a
[1, 2, 3]
>>> id(a)  # This will still have the same ID as it did originally
4315491720

>>> a = a + [4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]
>>> id(a)  # Now it will have a different ID because of the assignment operation
4315489736

推荐阅读