How to call class from another class in python - python-3.x

I am pretty new and trying to work on an algorithm challenge (Binary Inorder Traversal). I am trying to go through a tree (iterative) but for some reason there is a disconnect when I call the function.
from typing import List
from typing import Optional
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = []
stack = []
cur = root
while cur or stack:
while cur:
stack.append(cur)
cur = cur.left
cur = stack.pop()
res.append(cur.val)
cur = cur.right
print(res)
Solution.inorderTraversal(Solution,[1,'',2,3])
I get "list object has no attribute 'left error and also note that the second value in the root is supposed to be 'null' but when I use 'null' it says null is not defined.

Some things to consider:
Your classes are what you would typically expect in a LeetCode challenge. LeetCode will convert a JSON-like text input for you into a TreeNode instance and will then call your method with that as argument.
The description of such code challenges is most often language agnostic, so there will be mention of null, when in an actual programming language this will be None (Python), NULL (c), ...etc. This is something to take into account.
The function you need to implement is supposed to return the result. Printing it is not enough and not needed
When you want to call your function yourself, you cannot just pass a list as argument, you need to pass a TreeNode instance. For instance, like this:
# This is what LeetCode will do with "[1, null, 2, 3]"
root = TreeNode(1, None, TreeNode(2, TreeNode(3)))
result = Solution().inorderTraversal(root)
print(result)
If you want to dynamically build that TreeNode from a list, you can for instance use a function like provided here.

Here are a few things to take note of, that might help.
First, logically, every instance of your TreeNode class should have as its left and right nodes another instance of the TreeNode class. So to start with, I would change this:
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
...to this:
class TreeNode:
def __init__(self, val: int, left: Optional[TreeNode] = None, right: Optional[TreeNode] = None):
self.val = val
self.left = left
self.right = right
(Note: To use a class's name as a type annotation within the body of that class's definition without triggering a linting error, you may need to place from __future__ import annotations as the very first line of your file. If this is confusing/difficult just drop the type hints.)
Next, to make printing a bit easier on the eye, I suggest adding a __str__() method to your TreeNode class definition, like so:
def __str__(self):
# when printing a TreeNode instance, print its value
return str(self.val)
Next, and most significantly, your Solution class doesn't seem to be necessary. You don't really have a Solution "object" in play here, which rather begs the question - why define it as a class? Also, you have the method returning a list of integers - when in fact what you want it to do (going by the remainder of your method definition) is return a list of TreeNodes.
So your function might look something like this:
def inorderTraversal(root: TreeNode) -> List[TreeNode]:
res = []
cur = root
stack = []
while cur or stack:
while cur:
stack.append(cur)
cur = cur.left
cur = stack.pop(0)
res.append(cur)
cur = cur.right
return res
We can test this on a binary tree composed entirely of TreeNode objects:
root = TreeNode(
val=1,
left=TreeNode(val=2, left=TreeNode(val=4), right=TreeNode(val=5)),
right=TreeNode(val=3, left=TreeNode(val=6), right=TreeNode(val=7)),
)
res = inorderTraversal(root=root)
for node in res:
print(node)
This yields the result:
1
2
4
3
6
5
7

Related

How does nodes list get built up in __repr__(self) method while invoking other methods in class LinkedList

I'm trying to understand how the __repr__ method gets called and the nodes list gets updated during invocation of class's other methods. Sorry if my terminology isn't correct. I've only included the prepend and append methods for brevity. It looks to me like the list "nodes" would get initialized over and over again. Thanks!
class Node:
"""A node in a singly-linked list"""
def __init__(self, dataval=None, nextval=None):
self.dataval = dataval
self.nextval = nextval
def __repr__(self):
return repr(self.dataval)
class LinkedList:
def __init__(self):
"""Creating a new singly-linked list."""
self.head = None
def __repr__(self):
"""Creating a string representation of the data field in a list"""
nodes = []
curr = self.head
while curr:
nodes.append(repr(curr))
curr = curr.nextval
return '[' + '->'.join(nodes) + ']'
def prepend(self, dataval):
"""Insert a new element at the beginning of the list."""
self.head = Node(dataval=dataval, nextval=self.head)
def append(self, dataval):
"""Insert a new element at the end of the list."""
if not self.head:
self.head = Node(dataval=dataval)
return
curr = self.head
while curr.nextval:
curr = curr.nextval
curr.nextval = Node(dataval=dataval)
The code works, I just don't understand quite how it works. It's from an online course about data structures.
Inside the LinkedList's __repr__ you create a new local nodes list, you call the __repr__ of all of the nodes by passing on their nextval attribute and add their string representation to the list, and then concatenate the list together using '->'.join().
You can visualize it using python tutor starting from step 41.
You seem to be confused about the call to append in __repr__: that is not a call to the append method in your class. It is calling append on a native list type. The two methods happen to have the same name, and I guess that's where the mixup comes from.
The __repr__ method creates a list (not a LinkedList) and populates it with the string representations of the nodes in the linked list. Then it joins those strings to one string and returns it. During this process no other method of the LinkedList class is called.
__repr__ isn't called in the prepend and append routines. The nodes list in LinkedList.__rep__ is only there temporarily to hold the nodes while its return value is built. In fact, your classes don't use list to hold nodes at all. LinkedList has a reference to the first Node in head and each Node has a reference to the next node in nextval.

Is there a way to pass all variable to a function in python

I have part of a function I would like to turn into another function. I want this new function to be able to edit the variables in in the parent function. Is this possible in python.
I know in other languages that a class can inherent their parents variables and function. I am wondering if there is something similar to this in python?
check here for scoping then here and here for closures. You are ideally looking for enclosing functions. The variables defined within the enclosing functions are available to the sub-functions as though they were globally defined. Most of these are widely dealt with in other languages.
def m(x,y):
z = 2
j = 4
def n():
return x+y+z+j
return n()
m(3,1)
10
is that what you are looking for !
class Parent:
# two class variables x,y
x = 100
y = 100
def __init__(self):
pass
def sum_from_parent(self):
return self.x+self.y
class Child(Parent):
def __init__(self):
super().__init__() # init super class to create x,y variables
def sum_child(self):
# edit base class variables
x_in_child = Parent.x+20
y_in_child = Parent.y+20
return(x_in_child+y_in_child)
c = Child()
print("sum in parent = ", c.sum_from_parent())
print("sum in child = ", c.sum_child())
answer will be
sum in parent = 200
sum in child = 240

Generate all valid binary search trees given a list of values

Hello I am trying to solve the following question on leetcode, [https://leetcode.com/problems/unique-binary-search-trees-ii/].
I know I have access to the solution but I tried solving the problem my way and I am stuck and I would like to know if it is solvable the way I am doing it.
Here is the code:
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def generateTrees(myrange, n, res = None):
if res == None:
res = []
if myrange == []:
res.append(None)
return
for root in myrange:
res.append(root)
generateTrees([i for i in range(root) if i in set(myrange)], n, res) #leftchild
generateTrees([i for i in range(root+1, n) if i in set(myrange)], n, res) #rightchild
return res
Initially myrange is just the list containing the node values, and n is the length of myrange.
The way I am doing it is a sort of DFS where I loop over the nodes making each one of them the root once and then I do the same for the left and right subtrees to get all combinations. But the problem I am facing is I can't figure out how to manage res to remove elements from it as my recursion backtracks (and make it so res only contains valid bst's and then put those in some other list that will be my actual result).
I would like some pointers or even just comments on if you think my approach is valid or bad ..etc.
Issues:
As you mention, your code only creates one list to which it keeps appending.
Even if you would fix that, the lists would never come out in the BFS kind of order, which is what the question's example seems to suggest.
For a chosen root, you need to list all combinations of its possible left subtrees with its possible right subtrees -- a Cartesian product if you wish. This logic is missing in your code.
I would:
not pass res as argument to the recursive function. Just return it, and let the caller deal with it.
not use ranges, as that only seems to complicate things. The if i in set(myrange) seems like an inefficient way to get the overlap between two ranges. I would instead pass the two extremes of the range as separate arguments.
use the TreeNode class to actually create the trees, and deal with generating the required output format later.
For generating the output format you need a BFS walk through the tree, and this could be implemented as a method on TreeNode.
Here is what I think would work:
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def breadth_first(self):
lst = []
todo = [self]
while any(todo):
node = todo.pop(0)
lst.append(node.val if node else None)
if node:
todo.append(node.left)
todo.append(node.right)
return lst
def generateTrees(n):
def recur(start, end): # end is not included
if start >= end:
return [None]
trees = []
for root in range(start, end):
lefts = recur(start, root)
rights = recur(root+1, end)
# Cartesian product:
for left in lefts:
for right in rights:
# Start with a new tree, and append to result
tree = TreeNode(root)
tree.left = left
tree.right = right
trees.append(tree)
return trees
return recur(1, n+1)
# Create the trees as a list of TreeNode instances:
trees = generateTrees(3)
# Convert to a list of lists
print([tree.breadth_first() for tree in trees])

How to refer to an attribute of a first object, which creates with a method a second object?

I'm currently trying to build a simple animation for a queuing model and I want to set the coords of any graphical object in dependence of its predecessor object. To do so, I call a method of the object (o1), which I want to animate. This method creates an object (o2) of another class, which represents the image. While creating o2, I want to pass an attribute of o1. This looks, for instance, like this:
class Queue(salabim.Queue):
def setup(self, predecessor):
self.predecessor = predecessor
def animate(self, graphic):
self.graphic = graphic
buffer_preprocessing = Queue(
name = 'buffer_preprocessing',
predecessor = source)
if env.animation is True:
buffer_preprocessing.animate(graphic = Symbol_Queue(
width = 80,
height = ref_height,
slots = 5,
x = predecessor.graphic.x + predecessor.graphic.width + distance,
y = y0,
fillcolor = 'white'))
When compiling the program, I receive an error "[pylint] Undefined variable 'predecessor' [undefined-variable]".
Can somebody tell me, which keyword I need to use to refer to the attributes of the outside object "buffer_preprocessing"?
Thanks in advance :-)
Edit: It is possible to simplify my problem to the following code:
class OuterClass():
def __init__(self, A):
self.A = A
def do_stuff(self, stuff):
self.stuff = stuff
class InnerClass():
def __init_(self, B):
self.B = B
outerclass = OuterClass(A=1)
outerclass.do_stuff(stuff = InnerClass(B = 1 + A))
# Error: Undefined variable 'A'
# How can I refer to the calling object 'outerclass' without giving the explicit name?
I am guessing both the Queue and the Symbol_Queue since neither the name nor the predecessor parameters are part of python's queue.Queue.
If this is so, I believe the change needs to be implemented inside the code of the Queue class... maybe something along the lines:
First, expose the predecessor inside the Queue
class Queue(...):
def __init__(self, name, predecessor, ...):
...
# expose the predecessor
self.predecessor = predecessor
or alternatively, if you need to do some processing/checking you can expose a property
class Queue(...):
def __init__(self, name, predecessor, ...):
...
# expose the predecessor
self._predecessor = predecessor
#property
def predecessor(self):
# .. some checks or processing
return self._predecessor
Second, your code above will now become something like:
buffer_preprocessing = Queue(
name = 'buffer_preprocessing',
predecessor = source)
if env.animation is True:
buffer_preprocessing.animate(graphic = Symbol_Queue(
width = 80,
height = ref_height,
slots = 5,
x = buffer_preprocessing.predecessor.graphic.x + buffer_preprocessing.predecessor.graphic.width + distance,
y = y0,
fillcolor = 'white'))
There probably might be better ways to pass this by changing a little the implementation of the .animate, but it's hard to say without looking at the implementation of the Queue and Symbol_Queue classes.
EDIT 1: Using the simpler abstraction added to the question
I believe the key here would be to include some kind of logic inside the OuterClass.do_stuff, since in there you can access the things within self. Of course, it depends how much you can "hardcode" into this function on the OuterClass.
Here is a suggestion (I define the Inner first for better readability):
class InnerClass():
def __init_(self, B):
self.B = B
class OuterClass():
def __init__(self, A):
self.A = A
def do_stuff(self, stuff_to_create_inner):
new_inner = InnerClass(B = 1 + self.A, **stuff_to_create_inner)
# You can use "**" (dict unpacking), or pass them "by hand"
# ...
self.stuff = stuff
outerclass = OuterClass(A=1)
outerclass.do_stuff() # in your example you may want to pass the width, height, ...
Finally, should you need to use/keep track of that inner object you created (I'm guessing you don't since you simply create on inside the method call), you could always have OuterClass.do_stuff return the created object.
Thanks for the simplification. Now it’s much clearer. In that case, you can simply pass the class as well as the argument to do_stuff rather than creating an object when calling the do_stuff function. For example,
class OuterClass():
def __init__(self, A):
self.A = A
def do_stuff(self, my_class, other_input):
self.obj = my_class(other_input+self.A)
class InnerClass():
def __init_(self, B):
self.B = B
outerclass = OuterClass(A=1)
outerclass.do_stuff(my_class = InnerClass, other_input=1)

I have two classes(A and B), and I'm trying to use a method from A in B. The method in A, simply finds the index of an item in a list:

I have three classes(A, I and B), where A is inheriting from I. I'm trying to use a method ,from A, in B. The method in A, simply finds the index of an item in a list. I have:
File 1:
class I:
def__init__(self,s):
self.s = s
class A(I):
def __init__(self,n):
self.n = n
self.lst = []
for i in range(n):
self.lst.append([])
.....
def get_item_location(self, item):
for index in range(len(self.lst)):
if item in self.lst[index]:
return index
File 2:
from A import classA
class B:
def __init__(self,n):
self._model = A(n)
def something(self, dest_point):
print (self._model.get_item_location(self._item))
Where the type of self._item is Class I, now this prints None for me, where I expect it to return the index number of the list which the item is inside it, and the item is inside the list. When I used get_item_location function, it gives me an integer, but when Class B is using it, it returns None. I beleive it's something to do with that self._item, but I have not come up with any solution yet. I'd really appreciate it if someone could help.

Resources