Python 通过引用传递 class 的实例
Python passing instance of class by reference
所以 Python 并没有真正做到这一点。我有一个 class 树,它是二叉树类型。
class Tree(object):
def __init__(self):
self.left = None
self.right = None
self.data = None
def filler(self, lista, tree):
tree = Tree()
nr = len(lista)
nr //= 2
if len(lista) == 0:
return
if len(lista) == 1:
tree.data = lista[0]
return
tree.data = lista[nr]
self.filler(lista[:nr], tree.left)
self.filler(lista[nr:], tree.right)
函数filler()
将列表转换为二叉树。我试着这样称呼它:
tr = Tree()
tr2 = Tree()
l = self.ctrler.Backtrack(self.ctrler.tsk, 0) -- some list
tr.filler(l, tr2)
print(tr2.data)
结果是None
。 filler()
什么都不做。我能做些什么吗?我可以通过引用传递 tr2
对象吗?如果无法通过引用传递列表,如何将其转换为二叉树?
在填充器中没有实例化树的回溯:
Traceback (most recent call last):
File "D:/Projects/Python/AIExcavator/src/ui.py", line 75, in <module>
uier.inter()
File "D:/Projects/Python/AIExcavator/src/ui.py", line 63, in inter
tr.filler(l, tr2)
File "D:\Projects\Python\AIExcavator\src\Backtracking.py", line 79, in filler
self.filler(lista[:nr], tree.left)
File "D:\Projects\Python\AIExcavator\src\Backtracking.py", line 78, in filler
tree.data = lista[nr]
AttributeError: 'NoneType' object has no attribute 'data'
你写
tr.filler(l, tr2)
但是在 filler 中,你不使用 tr2,因为你用一个新的树对象擦除它。
def filler(self, lista, tree):
tree = Tree()
此外,正如评论中指出的那样,
self.filler(lista[:nr], tree.left)
self.filler(lista[nr:], tree.right)
是错误的,因为您传递了 tree.left
和 tree.right
,两者都是 None
,而 filler
需要一个 tree
对象,而不是 None
.
关于通过引用传递,您应该阅读Python中的mutables。 TL;DR: 如果你将 tr2
传递给 filler
并在 filler
中修改它,它确实会被修改。
filler
有点奇怪,因为它只需要 self
来进行递归调用。它实际上是一个备用构造函数,使其更适合作为 class 方法,例如
class Tree(object):
def __init__(self, data=None, left=None, right=None):
self.left = left
self.right = right
self.data = data
# The former method filler()
@classmethod
def from_list(cls, lista):
if lista:
# All non-empty lists are the same.
# Specifially, nr = 0 for a single-element list,
# and lista[:nr] and lista[nr+1:] are empty lists
# in the edge cases.
nr = len(lista) // 2
return cls(lista[nr],
cls.from_list(lista[:nr]),
cls.from_list(lista[nr+1:]))
else:
return None
tree = Tree.from_list([1,2,3,4,5,6])
使用 class 方法的好处是您可以定义 Tree
的子 class 而无需重新定义 from_list
。考虑
class BackwardsTree(Tree):
def __init__(self, data=None, left=None, right=None):
self.data = data
# Swap the left and right subtrees
self.right = left
self.left = right
bt = BackwardsTree.from_list([1,2,3,4,5,6])
虽然 BackwardsTree.from_list
解析为 Tree.from_list
因为你没有覆盖函数,return 值仍然是 BackwardsTree
的实例,而不是 Tree
,因为您使用 cls
来创建每个(子)树,而不是在方法中硬编码 Tree
。
所以 Python 并没有真正做到这一点。我有一个 class 树,它是二叉树类型。
class Tree(object):
def __init__(self):
self.left = None
self.right = None
self.data = None
def filler(self, lista, tree):
tree = Tree()
nr = len(lista)
nr //= 2
if len(lista) == 0:
return
if len(lista) == 1:
tree.data = lista[0]
return
tree.data = lista[nr]
self.filler(lista[:nr], tree.left)
self.filler(lista[nr:], tree.right)
函数filler()
将列表转换为二叉树。我试着这样称呼它:
tr = Tree()
tr2 = Tree()
l = self.ctrler.Backtrack(self.ctrler.tsk, 0) -- some list
tr.filler(l, tr2)
print(tr2.data)
结果是None
。 filler()
什么都不做。我能做些什么吗?我可以通过引用传递 tr2
对象吗?如果无法通过引用传递列表,如何将其转换为二叉树?
在填充器中没有实例化树的回溯:
Traceback (most recent call last):
File "D:/Projects/Python/AIExcavator/src/ui.py", line 75, in <module>
uier.inter()
File "D:/Projects/Python/AIExcavator/src/ui.py", line 63, in inter
tr.filler(l, tr2)
File "D:\Projects\Python\AIExcavator\src\Backtracking.py", line 79, in filler
self.filler(lista[:nr], tree.left)
File "D:\Projects\Python\AIExcavator\src\Backtracking.py", line 78, in filler
tree.data = lista[nr]
AttributeError: 'NoneType' object has no attribute 'data'
你写
tr.filler(l, tr2)
但是在 filler 中,你不使用 tr2,因为你用一个新的树对象擦除它。
def filler(self, lista, tree):
tree = Tree()
此外,正如评论中指出的那样,
self.filler(lista[:nr], tree.left)
self.filler(lista[nr:], tree.right)
是错误的,因为您传递了 tree.left
和 tree.right
,两者都是 None
,而 filler
需要一个 tree
对象,而不是 None
.
关于通过引用传递,您应该阅读Python中的mutables。 TL;DR: 如果你将 tr2
传递给 filler
并在 filler
中修改它,它确实会被修改。
filler
有点奇怪,因为它只需要 self
来进行递归调用。它实际上是一个备用构造函数,使其更适合作为 class 方法,例如
class Tree(object):
def __init__(self, data=None, left=None, right=None):
self.left = left
self.right = right
self.data = data
# The former method filler()
@classmethod
def from_list(cls, lista):
if lista:
# All non-empty lists are the same.
# Specifially, nr = 0 for a single-element list,
# and lista[:nr] and lista[nr+1:] are empty lists
# in the edge cases.
nr = len(lista) // 2
return cls(lista[nr],
cls.from_list(lista[:nr]),
cls.from_list(lista[nr+1:]))
else:
return None
tree = Tree.from_list([1,2,3,4,5,6])
使用 class 方法的好处是您可以定义 Tree
的子 class 而无需重新定义 from_list
。考虑
class BackwardsTree(Tree):
def __init__(self, data=None, left=None, right=None):
self.data = data
# Swap the left and right subtrees
self.right = left
self.left = right
bt = BackwardsTree.from_list([1,2,3,4,5,6])
虽然 BackwardsTree.from_list
解析为 Tree.from_list
因为你没有覆盖函数,return 值仍然是 BackwardsTree
的实例,而不是 Tree
,因为您使用 cls
来创建每个(子)树,而不是在方法中硬编码 Tree
。