Python 传递对象引用值
Python pass by object reference value
我正在尝试在 python 中编写一个算法来打印出从(二叉)树的根到每个叶子的所有路径。这是我的代码:
def fb_problem(node, curr_trav):
curr_trav = curr_trav + [node]
if node.left is None and node.right is None:
for path_node in curr_trav:
print path_node.data
print "XXX"
if node.left is not None:
fb_problem(node.left, curr_trav)
if node.right is not None:
fb_problem(node.right, curr_trav)
fb_problem(root, [])
我在当前遍历中保留了一个节点列表,当我到达一个叶子节点时,我打印出该列表。不过,我对 python 传递对象的方式有些误解。我 认为 当每个递归调用完成并从堆栈中弹出时,原始 curr_trav
变量不会受到递归调用所做的影响。但是,似乎行
curr_trav += [node]
正在改变原始列表。 +=
运算符 returns 一个新列表,与 .append()
相反,它实际上改变了原始对象。那么这个调用不应该只是重新分配给函数中对象的名称,而不是改变原始对象吗?当我将行更改为
t_trav = curr_trav += [node]
一切正常,但我不明白原来的线路有什么问题。如果我的问题不清楚,请告诉我。
对于 python,它既不是按值也不是按引用。它是两者的结合,取决于传递给函数的对象类型。例如,如果传入 dict, list etc
等可变类型,它将传递引用。而对于诸如 str
之类的不可变类型,它将按值。 Jeff Knupp.
是一本关于这个主题的好书
您的原始代码 curr_trav += [node]
的问题是它将 [node]
的值添加到 curr_trav
并将引用设置为新列表。因为它传递了 curr_trav
的引用,所以它将在每次后续迭代中更改。
您对+=
的理解不太正确。 Python 中的所有运算符实际上只是快捷方式。例如,如果 a
有一个 __add__
方法,a + b
就是 a.__add__(b)
。如果a
没有,那就是b.__radd__(a)
。如果 b
没有该方法,则会引发错误。通常,a += b
的行为与 a = a + b
非常相似,但在可变对象的情况下,它通常不会。这是因为如果 a
有 __iadd__
方法,a += b
就是 a.__iadd__(b)
。如果 a
没有,则与 a = a.__add__(b)
相同。如果 a
也没有,则与 a = b.__radd__(a)
相同。由于列表 do 具有 __iadd__
方法,实际的列表对象被更改而不是重新定义 curr_trav
.
我正在尝试在 python 中编写一个算法来打印出从(二叉)树的根到每个叶子的所有路径。这是我的代码:
def fb_problem(node, curr_trav):
curr_trav = curr_trav + [node]
if node.left is None and node.right is None:
for path_node in curr_trav:
print path_node.data
print "XXX"
if node.left is not None:
fb_problem(node.left, curr_trav)
if node.right is not None:
fb_problem(node.right, curr_trav)
fb_problem(root, [])
我在当前遍历中保留了一个节点列表,当我到达一个叶子节点时,我打印出该列表。不过,我对 python 传递对象的方式有些误解。我 认为 当每个递归调用完成并从堆栈中弹出时,原始 curr_trav
变量不会受到递归调用所做的影响。但是,似乎行
curr_trav += [node]
正在改变原始列表。 +=
运算符 returns 一个新列表,与 .append()
相反,它实际上改变了原始对象。那么这个调用不应该只是重新分配给函数中对象的名称,而不是改变原始对象吗?当我将行更改为
t_trav = curr_trav += [node]
一切正常,但我不明白原来的线路有什么问题。如果我的问题不清楚,请告诉我。
对于 python,它既不是按值也不是按引用。它是两者的结合,取决于传递给函数的对象类型。例如,如果传入 dict, list etc
等可变类型,它将传递引用。而对于诸如 str
之类的不可变类型,它将按值。 Jeff Knupp.
您的原始代码 curr_trav += [node]
的问题是它将 [node]
的值添加到 curr_trav
并将引用设置为新列表。因为它传递了 curr_trav
的引用,所以它将在每次后续迭代中更改。
您对+=
的理解不太正确。 Python 中的所有运算符实际上只是快捷方式。例如,如果 a
有一个 __add__
方法,a + b
就是 a.__add__(b)
。如果a
没有,那就是b.__radd__(a)
。如果 b
没有该方法,则会引发错误。通常,a += b
的行为与 a = a + b
非常相似,但在可变对象的情况下,它通常不会。这是因为如果 a
有 __iadd__
方法,a += b
就是 a.__iadd__(b)
。如果 a
没有,则与 a = a.__add__(b)
相同。如果 a
也没有,则与 a = b.__radd__(a)
相同。由于列表 do 具有 __iadd__
方法,实际的列表对象被更改而不是重新定义 curr_trav
.