I'm trying to implement a recursive method to calculate the height of a binary tree. Here is the "height"-code:
def HeightOfTree(self):
if self.root is None:
return 0
else:
ans=self._HeightOfTree(self.root)
return ans
def _HeightOfTree(self,currentNode):
if currentNode.hasleftChild():
lheight=1+self._HeightOfTree(currentNode.leftChild)
if currentNode.hasrightChild():
rheight=1+self._HeightOfTree(currentNode.rightChild)
if lheight > rheight:
return (lheight+1)
else:
return (rheight+1)
When I try to call the function, I get the following error msg:
UnboundLocalError: local variable 'lheight' referenced before assignment
How can I fix this problem ?
If you're setting the value of a variable in an if block and you try to use it later, make sure that it's declared before the block so that if the if doesn't happen, it still exists.
Wrong:
if False:
x = 3
print(x)
# UnboundLocalError
Right:
x = 0
if False:
x = 3
print(x)
# 0
You are getting the UnboundLocalError because the values rheight and lheight are not created in the case that leftChild or rightChild are None.
It would be simpler if you defined a base case of _HeightOfTree(None) == 0:
def _HeightOfTree(self,currentNode):
if currentNode is None:
return 0
return 1 + max(self._HeightOfTree(currentNode.leftChild), self._HeightOfTree(currentNode.rightChild))
Related
here is some code. I want to make an if statement but only when a variable has increased
while True:
a += 1
if a ????
print('a has changed')
Here is an option.
while True:
previous = a
# do stuff
a += 1
if a != previous:
print('a has changed')
Here is a way you can do this:
while True:
old_a = a #Create a variable for the old value of a
a += 1
if a > old_a: #Check the condition if value of a has increased.
print('a has changed')
A more clever way using the python Observer pattern.
class observe_value_change():
def __init__(self):
self._initial = 1
#property
def position(self):
return self._initial
#position.setter
def position(self, new_value):
self._initial = new_value
print("execute more code here!")
print(self._initial)
To test
p = observe_value_change()
print(p.position)
p.position = 4
Explanation:
When the value of position changes, it will call the position setter method otherwise it will not be called.
So, the if block can be written inside the position setter method.
I have a class for a Dialogue system as follows
class DIALOGUE(object):
def __init__(self, place, who, sTime, eTime, isActive, mood, menuText, func, repeatable, num):
self.place = place
self.who = who
self.sTime = sTime
self.eTime = eTime
self.isActive = isActive
self.mood = mood
self.menuText = menuText
self.func = func
self.repeatable = repeatable
self.num = num
#property
def ACheck(self):
global Date
if self.sTime == "none":
return True
else:
tHour,tMin = self.sTime.split(":")
if tHour >= Date.Hour and tMin <= Date.Minute:
tHour,tMin = self.eTime.split(":")
if tHour < Date.Hour and tMin < Date.Minute:
return True
return False
#property
def BCheck(self):
global Act
if self.who == Act:
return True
else:
return False
#property
def CCheck(self):
global Location
if self.place == Location:
return True
if self.place == "none":
return True
return False
#property
def DCheck(self):
if self.repeatable:
return True
else:
if self.num > 0:
return False
else:
return True
#property
def CanChat(self):
if self.isActive and self.ACheck and self.BCheck and self.CCheck and self.DCheck:
return True
else:
return False
def SetActive(self):
self.isActive = True
def Do(self):
self.num += 1
renpy.call(self.func)
Most of this should be self explanatory but I parse an XML file into a list of Instances of this class.
The user is presented with a list of available dialogues based on what Location they are in, what time of day it is and what NPC they have selected. If the dialogue is not repeatable The DCheck method looks at whether or not the dialogue has been completed before i.e if the dialogue is not repeatable and self.num > 0 the method will return False
Essentially it loops through all the dialogues and carries out i.CanChat and if this value returns True, the Dialogue is added to the menu
The issue I'm having is that the Check methods aren't returning the correct value. Specifically DCheck is returning True all the time, regardless of whether the Dialogue is repeatable or not, and ignoring the value of self.num
The class is created in an init python: block and then the xml file is parsed in a separate python block which is called from inside the start label
It's probably something really simple but I can't figure it out.
The list of instances is parsed as follows
Dialogues = []
for j in Dialo:
JPlace = j.find('Place').text
JWho = j.find('Who').text
JsTime = j.find('Start').text
JeTime = j.find('End').text
JMood = int(j.find('Mood').text)
JText = j.find('Text').text
JFunc = j.find('Func').text
JRep = j.find('Rep').text
if JRep == "True":
Jrep = True
else:
Jrep = False
Dialogues.append(DIALOGUE(JPlace, JWho, JsTime, JeTime, False, JMood, JText, JFunc, JRep, 0))
The method for creating the menu is as follows
def TalkCheck():
talks = []
talks.append(("Nevermind.", "none"))
for i, q in enumerate(Dialogues):
if q.CanChat:
talks.append((q.menuText,i))
renpy.say(None, "", interact=False)
talkchoice = renpy.display_menu(talks)
if talkchoice <> "none":
talkchoice = int(talkchoice)
Dialogues[talkchoice].Do()
Your question is incomplete - you didn't post a MCVE, we don't know the effective values for "repeatble" and "num" that leads to this behaviour, and we don't even know if it's using Python 2.x or Python 3.x - so we can just try and guess. Now since you mention that you "parse an XML file into a list of instances", I stronly suspect you are running Python 2.x and passing those values as strings instead of (resp.) boolean and int. In Python 2, "-1" (string) compares greater than 0 (int) - it raises a TypeError in Python 3.x -, and in both cases a non-empty string evals to True in a boolean context (bool('False') == True). Since there's no obvious logical error in your method implementation, that's the only explanation I can think of.
BTW, expressions have a boolean values and return exits the function, so you can simplify your code:
#property
def DCheck(self):
if self.repeatable:
return True
return self.num > 0
How can I return the value of total_square only when quasi_gen==0? If I put another return statement to the case where quasi_gen>0, then it always returns zero.
def count_boxes(quasi_gen, initial_list):
total_square=0
new_list=[]
new_list=[box * 2 for box in initial_list]
concatenate_list=initial_list+new_list
if quasi_gen>0:
quasi_gen-=1
count_boxes(quasi_gen, concatenate_list)
elif quasi_gen==0:
total_square=(sum(elem for elem in concatenate_list))
return(total_square)
count_boxes(4, [2,2])
Not sure what you're trying to do but first of all you should safe guard against quasi_gen < 0
you also don't need to do all those useless resets, in short, try this:
def count_boxes(quasi_gen, initial_list):
concatenate_list=initial_list + [box * 2 for box in initial_list]
if quasi_gen < 0:
return 0 # ?
if quasi_gen > 0:
return count_boxes(quasi_gen - 1, concatenate_list)
return(sum(elem for elem in concatenate_list))
You have to call return on the first if/else branch:
if quasi_gen>0:
quasi_gen-=1
return count_boxes(quasi_gen, concatenate_list)
Like this you will be returning the result of the recursive call.
def str_tree(atree,indent_char ='.',indent_delta=2):
def str_tree_1(indent,atree):
if atree == None:
return ''
else:
answer = ''
answer += str_tree_1(indent+indent_delta,atree.right)
answer += indent*indent_char+str(atree.value)+'\n'
answer += str_tree_1(indent+indent_delta,atree.left)
return answer
return str_tree_1(0,atree)
def build_balanced_bst(l):
if len(l) == 0:
return None
else:
mid = (len(l)-1)/2
if mid >= 1:
build_balanced_bst(l[:mid])
build_balanced_bst(l[mid:])
else:
return
I am working on the build_balanced_bst(l), the build_balanced_bst(l) takes a list of unique values that are sorted in increasing order. calling build_ballanced_bst( list(irange(1,10)) returns a binary search tree of height 3 that would print as:
......10
....9
..8
......7
....6
5
......4
....3
..2
....1
the str_tree function is used to print what the build_balanced_bst() function returns. my str_tree function is correct, I cannot change it. I can only change the build_balanced_bst() function.
I used the middle value in the list as the root’s value. when I try to call the build_balanced_bst(l) in the below, it does not print anything.
l = list(irange(1,10))
t = build_balanced_bst(l)
print('Tree is\n',str_tree(t),sep='')
can someone help me to fix my build_balanced_bst(l) function? many thanks.
str_tree() doesn't do anything: It just defines a nested function and implicitly returns None.
As a start, you can have str_tree do something:
def str_tree(atree, indent_char ='.', indent_delta=2):
def str_tree_1(indent, atree):
# Note that str_tree_1 doesn't use the indent argument
if atree == None:
return ''
return str_tree_1(indent_delta, atree)
But this is just a start.
when I run this program, it print NameError global name 'viewAll' is not defined
I' m a C programmer, I didn't know why.
viewAll(this) is defined in class binTree,
Platform:Python 2.7 in windows 7 64 bit
#!/usr/bin/python
#-*-coding:gbk-*-
class binTree():
def __init__(this, left = None, right = None, data = 0):
if data == 0:
this = None
else:
this.leftNode = left
this.rightNode = right
this.data = data
def viewAll(this):
if this != None:
print this.data,
viewAll(this.leftNode)
viewAll(this.rightNode)
def creatBT():
temp = input('Please input a number, input "0" for end!')
if temp == 0:
return None
else:
tree = binTree()
tree.data = temp
tree.leftNode = creatBT()
tree.rightNode = creatBT()
return tree
if __name__ == "__main__":
root = creatBT()
root.viewAll()
You need to do a Python tutorial -- you're not understanding how the instance object works in Python instance methods.
Your problem is here:
def viewAll(this):
if this != None:
print this.data,
viewAll(this.leftNode)
viewAll(this.rightNode)
You need to access viewAll on the instance you want to call it on:
def viewAll(this):
if this != None:
print this.data,
this.leftNode.viewAll()
this.rightNode.viewAll()
I'm not sure what you're intending to do here:
if data == 0:
this = None
but all you are actually doing is pointing the name this at None in the scope of that one function call. It doesn't change anything about the class instance or anything outside the function.
So, in viewAll,
if this != None:
will always be True, because this is again the instance you've called viewAll on -- it hasn't been and can't be set to None.
class binTree():
# I removed __init__ to show you weren't using it
def viewAll(self):
print self.data,
# don't try to show a node that is empty
if self.leftNode:
self.leftNode.viewAll()
if self.rightNode:
self.rightNode.viewAll()
def creatBT():
try:
# don't use input
temp = int(raw_input('Please input a number, input "0" for end!'))
except ValueError:
# in case they don't put in a number
temp = 0
if temp == 0:
return None
else:
tree = binTree()
tree.data = temp
tree.leftNode = creatBT()
tree.rightNode = creatBT()
return tree
if __name__ == "__main__":
root = creatBT()
# don't try to show the nodes if none were created
if root:
root.viewAll()
Please conform to the standard and use self instead of this.
def viewAll(self):
print self.data,
self.viewAll(self.leftNode)
self.viewAll(self.rightNode)
There is no need to test if self (or this) is None.
edit This solution is not correct. Please see agf's answer.