Python object instantiation - python

I am very new to python and need some help with instantiating an object. The python interpreter is giving me trouble when instantiating an object of a class I defined. There are two classes, BTNode and BST (which are stored in files bst_node.py and bst.py respectively):
# file: bst_node.py
class BTNode:
"""a binary search tree node implementation"""
def ___init___(self, value):
self.value = value
self.left is None
self.right is None
self.parent is None
def ___init___(self, value, left, right, parent):
"""set the parameters to corresponding class members"""
self.value = value
self.left = left
self.right = right
self.parent = parent
def is_leaf(self):
"""check whether this node is a leaf"""
if self.left.value is None and self.right.value is None:
return True
return False
# file: bst.py
from bst_node import *
class BST:
"""a binary search tree implementation"""
def ___init___(self, value):
self.root = BTNode(value)
def insert(self, curRoot, newValue):
if curRoot.is_leaf():
if newValue < curRoot.value:
newNode = BTNode(newValue, None, None, curRoot)
curRoot.left = newNode
else:
newNode = BTNode(newValue, None, None, curRoot)
curRoot.right = newNode
else:
if newValue < curRoot.value:
self.insert(curRoot.left, newValue)
else:
self.insert(curRoot.right, newValue)
So, in the interpreter I do:
import bst as b
t1 = b.BST(8)
and I get an error which says that this constructor takes no arguments
The constructor clearly takes an argument value so what is going wrong here? How can I fix this error?
Thanks, all help is greatly appreciated!

The first issue is that you called your functions ___init___ instead of __init__. All of the 'special methods' use two underscores.
A second issue in this code is that in BTNode you redefined __init__. You can't overload functions in python. When you reclare __init__ you effectively deleted the first constructor.
A third issue is your usage of is. is is an operator that checks whether two objects are exactly the same and returns True or False. In the constructor, you have a few self.left is None is examining the value of self.left (which wasn't declared yet), and examining whether or not it is None. To set it, use = as follows:self.left = None
To fix the second and third issue you should use default argument values. For example:
def __init__(self, value, left=None, right=None, parent=None):

In addition to the number of underscores problem, you should replace
def ___init___(self, value):
self.value = value
self.left is None
self.right is None
self.parent is None
def ___init___(self, value, left, right, parent):
"""set the parameters to corresponding class members"""
self.value = value
self.left = left
self.right = right
self.parent = parent
with
def __init__(self, value, left=None, right=None, parent=None):
"""set the parameters to corresponding class members"""
self.value = value
self.left = left
self.right = right
self.parent = parent
Because as #Moshe points out, you can't overload functions, you should use default arguments insted.

Changing ___init___ to __init__ should fix it. (2 underscores vs 3)

Related

How to do tree traversal?

So I am running into some issue that has left me dumbfounded. I do not understand where I am going wrong with my code but the idea I have is I check if the current node I am at is None and if it is then I return a list of my tree in in order, pre order, and post order. Here is my code:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def inOrder(self, arr=[]):
if self is not None:
self.left.inOrder(arr)
arr.append(self.data)
self.right.inOrder(arr)
return arr
When I run it I get an error of self.left.inOrder() AttributeError: 'NoneType' object has no attribute 'inOrder' which I have not idea as to why. I am checking that self is not None so shouldn't this guarantee my Node to have a left and right.
I am only showing the inOrder I have implemented.
I have solved this instead by doing the following
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def inOrder(self):
if self is not None and self.left is not None:
self.left.inOrder()
print(self.data)
if self is not None and self.right is not None:
self.right.inOrder()
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.inOrder()
Whether I save it to a list or just print it is fine with me but if I already check if self is not None then shouldn't I be able to call self.left.inOrder and self.right.inOrder?
self is not None. self refers to an instance of the class. self.left is an instance attribute that you set to None in your __init__() method when you create the instance. Because self.left refers to None and the object None does not have the inOrder() method, you obtain an AttributeError. Within your class definition, self (referring to an instance of the class) does have the inOrder() method, but it's attribute self.left (referring to None), does not.

Extract min value node [duplicate]

This question already has answers here:
Python min function with a list of objects
(4 answers)
Closed 1 year ago.
I have the following class:
class Node:
def __init__(self, node, value, left=None, right=None):
self.node = node
self.value = value
self.left = left
self.right = right
self.code = ''
I have a list of Node. The question is, how can I extract the node with the lowest self.value attribute?
You could use the built-in min function with an anonymous function to access value parameter:
min(listNodes, key=lambda x: x.value)
Or you can define the rich comparison methods __lt__ and __eq__ in Node (you can define additional rich comparison methods, but these two are sufficient for ordering like min):
class Node:def __init__(self, node, value, left=None, right=None):
self.node = node
self.value = value
self.left = left
self.right = right
self.code = ''
def __iter__(self):
return self
def __lt__(self, other):
return self.value < other.value
def __eq__(self, other):
return self.value == other.value
which will allow min to directly compare the nodes finding the minimum!
min(listNodes)
Before Python3, it was possible to use the now-deprecated __cmp__ method to create all the rich comparison methods at once; see Question About This and Linked Official Notes

tree.put(key, value) insertion

So I'm working on an assignment for a data structures class, and one question is to create a put(key, value) method for an AVLTree. I know I have to adding the balancing method, but right now I'm just on the actual insertion. I want the function to work where you can create a tree and type newTree.put(key value) and have it work. Right now I have
class node:
def __init__(self, key, value):
self.key = key
self.value = value
self.left = None
self.right = None
self.height = 0
class AVLTreeMap:
def __init__(self, key, value):
self.root = node(key, value)
#inserting new key-value pair, NEED TO ADD BALANCING ABILITY
def put(self, key, value, height=0):
if(key < self.root.key):
if(self.root.left == None):
self.root.left = node(key, value)
self.root.left.height = height+1
else:
self.root = self.root.left
self.put(key, value, height+1)
else:
if(self.root.right == None):
self.root.right = node(key, value)
self.root.right.height = height+1
else:
self.root = self.root.right
self.put(key, value, height+1)
However, the recursive aspect of put just discounts the root, and creates a new tree of just one parent and that node as one child. Is this the right way to go about this, or is there an easier way? Also, if I do it this way, how do you recurse left and right in this method?

Python: AttributeError: 'NoneType' object has no attribute 'val' Line:14

I am trying to traverse a tree but getting above error. Please help me out. I am trying to call a definition of same class and as parameter sending a class object. But calling definition not able to identify type of parameters.
Definition for a binary tree node.
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution(object):
def same(self, s, t):
if(s is None and t is None):
return True
if(s is None or t is None):
return False
return s.val==t.val and self.same(s.left,t.left) and self.same(s.right,t.right)
def traverse(self, s, t):
return (s!="" and (self.same(s,t) or self.traverse(s.left,t) or self.traverse(s.right,t)))
def isSubtree(self, s, t):
# print s.val
return self.traverse(s,t)
The problem looks like it is the '' check as opposed to a None check in traverse. It will pass None values to same because of this.
Assuming that t and s are TreeNode objects, where do you declare them? Is it possible that you're passing undeclared variables to Solution?

default argument in recursive class method of python

Inside a recursive class function, how do i use a class member as default argument?
I am currently using following snippet that works (python 3). height is recursive class function. Default argument that i want to use for node is self._root. In order to achieve this, i do something like following but thats a very round about way where i have to define another function height_tree. Is there a more direct approach?
# following code works #
class BTree:
def __init__(self, node=None):
self._root = node
def height_tree(self):
return self.height(self._root)
def height(self, node):
if node is not None:
height = max(self.height(node.get_left()), self.height(node.get_right())) + 1
else:
height = 0
return height
I want to do something like following but it obviously doesn't works !
def height(self, node=self._root)
# code from above follows
I however cannot use alternate trick of assigning root to node when node is None since that is one of the end condition in recursion
def height(self, node)
if node is None:
node = self._root
# this will conflict with logic in code block above#
Are there any recommended ways to handle such a situation?
You can use a sentinel object:
sentinel = object()
def height(self, node=sentinel)
if node is sentinel:
node = self._root
...
Since such object would have a unique memory address, it would never be identical to any other object (including None).
You can always create arbitrary sentinels:
SENTINEL = object()
class BTree:
def __init__(self, node=None):
self._root = node
def height_tree(self):
return self.height(self._root)
def height(self, node=SENTINEL):
if node is SENTINEL:
node = self._root
elif node is not None:
height = max(self.height(node.get_left()), self.height(node.get_right())) + 1
else:
height = 0
return height

Categories