References in python classes on self
I expet that this code should output:
8
8but it does not.
class tree:
def __init__(self, size=2):
if size == 0:
return Non开发者_如何学JAVAe
if size > 1:
half = size//2
self.left = tree(size-half)
self.right = tree(half)
else:
self.left = self.right = None
self.free = size
self.size = size
def resize(self,n):
while self.size < n:
t = tree(0)
t.left = self
t.right = tree(self.size)
t.free = t.left.size + t.right.size
t.size = self.size * 2
self = t
print("size in resize", self.size)
t = tree()
t.resize(5)
print("size of t", t.size)
output:
size in resize 8
size of t 2
I know I could do return self
in resize
and t = tree.resize(5)
in main, but what if I want to return something else?
Karl's answer is entirely right about everything, but there is certainly a way to make resize
act as you're expecting.
Three steps:
- Make a copy of the tree
- Re-initialize the tree so it's the next size larger
Set the enlarged tree's
left
to the copy of the original treedef resize(self,n): while self.size < n: new = self.copy() self.__init__(int(round(self.size, 2)) * 2) self.left = new print("size in resize",self.size) def copy(self): new = tree(1) new.left = self.left new.right = self.right new.size = self.size new.free = self.free return new
Basically, you were trying to do it backwards -- replace self
and reuse self
for self.left
, instead of replacing self.left
and reusing self
.
self = t
This does not, and cannot be rewritten to, do what you want. There is nothing "special" about the name self
in Python; it's just like any other variable (the fact that you have to pass it explicitly to methods should have been your first hint, unlike in languages that treat this
as a keyword, should have been your first hint ;) ), and like all other variables, it has reference semantics.
self = t
means "from this point onward (until another re-definition or the end of scope), self
no longer refers to what that self
parameter referred to, but instead to the value that t
refers to".
Also, you have a typo in one case of your __init__
method ('rigt'), and I assume that the number of free
nodes is supposed to be an invariant something like size - occupied
; in which case it would be cleaner to count the occupied nodes and use a method or property to calculate the free ones, instead of trying to update that count on every modification.
(Moreover, what you seem to be trying to do is all kinds of un-Pythonic. In particular, the idea of a container having a specific "allocated size" is strange; that sort of thing normally only matters on the C side of the fence. What do you need a binary tree for? Also, this method isn't going to balance the tree at all. And what use is a tree if none of the nodes store any data?)
精彩评论