Checking if object inside heap - python

I am trying to check if an object is inside a heap. However, I keep getting this error:
AttributeError: 'tuple' object has no attribute 'X'
I have a Heap and a Cell class that look like this:
import heapq
class Heap(object):
def __init__(self):
self.heap = []
def push(self, priority, cell):
heapq.heappush(self.heap, (priority, cell))
def pop(self):
cell = heapq.heappop(self.heap)[1]
return cell
def contains(self, cell):
if(cell in self.heap):
return True
return False
def isEmpty(self):
return len(self.heap) == 0
Cell class:
class Cell(object):
def __init__(self, x, y):
self.X = x
self.Y = y
def __eq__(self, other):
return int(self.X) == int(other.X) and int(self.Y) == int(other.Y)
I use the Heap class like this: I get the error when I use the contains method.
from Heap import Heap
from Cell import Cell
class Test(object):
def __init__(self):
self.myHeap = Heap()
cell = Cell(2, 3)
self.myHeap.push(1, cell)
if self.myHeap.contains(cell) == False:
print("not in heap")
test = Test()
What am I doing wrong? Any help would be appreciated.

The problem is in containsmethod.
def contains(self, cell):
if(cell in self.heap):
return True
return False
self.head is a list of tuples of type (priority, Cell). And you actually compares Cells with elements of this list (tuples), so Cell.__eq__() method is called and it raises exception.

Related

Python class does not have value

I am a Javascript engineer and am switching into a JS/Python role. Working on some easy leetcodes to get some quick Python practice.
I'm looking to create a LinkedList here and perhaps I am coming at it from a JS mindset?
Error:
AttributeError: type object 'LinkedListNode' has no attribute 'value'
utils.py
# LinkedList Methods
def createLinkedList(arr):
head = createLinkedListNode(None, arr.pop(0))
def populateList(arr, prevNode):
if arr:
node = createLinkedListNode(None, arr.pop(0))
prevNode.next = node
if arr:
populateList(arr, node)
populateList(arr, head)
return head
def createLinkedListNode(next, value):
class LinkedListNode:
def __init__(self):
self.next = next
self.value = value
return LinkedListNode
deleteNode.py
from python.utils import createLinkedList, linkedListToArray
useCase1 = [4, 5, 1, 9]
linkedList = createLinkedList(useCase1)
^ linkedList.value doesn't exist?
Some misunderstandings with python classes:
The class LinkedListNode should not defined in function.
Return LinkedListNode is actually returning the class itself, but not the Instance. To return the instance, you have to call the class. return LinkedListNode()
Using next as instance variable is not ideal. next is an iteration function in python, so when you set self.next = next, you are actually assigning the function to self.next
If you want to set a variable, for example self.next_value = next_value, you should put next_value as a parameter of __init__ function, like def __init__(self, next_value)
Here is a simple demo of Linked List:
class LinkedList:
def __init__(self, value):
self.value = value
self.next_value = None
def __iter__(self):
yield self.value
if self.next_value is not None:
yield from self.next_value
# else raise StopIteration
def __getitem__(self, index):
if index == 0:
return self.value
else:
return self.next_value[index-1]
# recursively get the next value
def __str__(self):
return str(self.value) + ' -> ' + str(self.next_value)
def __len__(self):
if self.next_value is None:
return 1
else:
return 1 + len(self.next_value)
# recursively get the length
def append(self, value):
if self.next_value is None:
self.next_value = LinkedList(value, self)
else:
self.next_value.append(value)
a = LinkedList(2)
a.append(1)
a.append(3)
for num in a:
print(num, end=", ")
print()
print(a[1])
print(a)
print(len(a))
Output:
2, 1, 3,
1
2 -> 1 -> 3 -> None
3
createLinkedListNode() returns the LinkedListNode class itself, not an instance of the class.
Why are you defining classes and functions inside of other functions? That's an odd way of doing things.

How to add items to a list properly

I am currently learning python. I am learning about classes, inheritance, and abstract classes. Here is the constructor in question:
def __init__(self, sourceCollection = None):
"""Sets the initial state of self, which includes the
contents of sourceCollection, if it's present."""
self.size = 0
if sourceCollection:
for item in sourceCollection:
self.add(item)
I am getting the following error, and I don't know why:
TypeError: 'int' object is not iterable
In case is helps, here is my add method:
def add(self, item):
"""Adds item to self."""
# Check array memory here and increase it if necessary
self.items[len(self)] = item
self.size += 1
Could anyone assist me with why I am getting this error? I did some research, but to no avail. Thanks so much in advance!!!
list has a method to add all elements from an iterable
Don't use self.size to keep track of the number of elements in self.items, use len(self.items)
def __init__(self, sourceCollection = None):
"""Make a copy of sourceCollection"""
self.items = []
if not sourceCollection: return
self.items.extend(sourceCollection)
def add(self, item):
"""Adds item to self."""
self.items.append(item)
#property
def size(self):
return len(self.items)
Just do (.append()):
def add(self, item):
"""Adds item to self."""
# Check array memory here and increase it if necessary
self.items.append(item)
self.size += 1

Class iteration over internal numpy array ? Assignment?

How do you make class to iterate by its internal numpy array :
Just idea which does not work :
class ABC:
def __init__(self):
self.ary = np.zeros(50)
def __iter__(self): return np.nditer(self.ary)
def next(self): ...??..
Also how to make assignment work too :
abc = ABC()
abc[5] = 12
abc[7:9] 0
From documentation,
iterator.__next__():
Return the next item from the container. If there are no further items, raise the StopIteration exception. This method corresponds to the tp_iternext slot of the type structure for Python objects in the Python/C API.
For setting and getting values for container class, you need to implement __getitem__ and __setitem__.
For your sample code
class ABC():
def __init__(self):
self.ary = np.zeros(50)
self.index = self.ary.shape[0]
def __iter__(self):
return np.nditer(self.ary)
def next(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
def _check_indx(self, idx):
if abs(idx) >= self.ary.shape[0]:
raise IndexError(f"Invalid Index {idx} for array with shape {self.ary.shape}")
def __setitem__(self, idx, value):
self._check_indx(idx)
self.ary[idx] = value
def __getitem__(self, idx):
self._check_indx(idx)
return self.ary[idx]

What method do I need to override for list child to return internal data array instead of itself?

I needed a dynamic size queue so I inherited list and Iterable and I tested all the stuff like appending, indexing and iterating but there is a small problem. Methods like
str(DataSet) return an empty list, and the Python debugger does show an empty list, which is expected, since I don't append to the list parent but the internal data. What do I need to override to not return self but return self.data?
class DataSet(collections.Iterable, list):
data = collections.deque()
index = 0
max = 3
def __add__(self, other):
self.append(other)
def append(self, item):
if len(self.data) >= self.max:
self.data.popleft()
self.data.append(item)
def __next__(self):
if self.index < len(self.data):
ret = self.data[self.index]
self.index += 1
return ret
raise StopIteration
def __getitem__(self, i):
return self.data[i]
def __iter__(self):
self.index = 0
return self
def setMax(self, max):
self.max = max
def __len__(self):
return len(self.data)
Override
def __str__(self):
return str(self.data)

Implement and/or tree in python

I need to implement an And/or tree in python so I can evaluate boolean expressions,
I had an idea of creating a class that contains andNode, orNode and leafNode. The first two are are internal nodes that must have and or or values, the leafNode must have and integer value and represent the final leaves of the tree.I tried this but it doesn't seem to work:
class Node:
def __init__(self,leaf):
self.orNode = None
self.andNode = None
self.leaf = leaf
class and_or_tree (Node):
def __init__(self):
self.root=None
I need to test if an element exists in the tree, the height and iterate through it.
I think an example of such Leaf and and/or nodes could be something like this:
class Leaf:
def __init__(self, v):
self.val = v;
def __call__(self):
return self.val
class AndNode:
def __init__(self, l, r):
self.left = l;
self.right = r;
def __call__(self):
return self.left() and self.right()
class OrNode:
def __init__(self, l, r):
self.left = l;
self.right = r;
def __call__(self):
return self.left() or self.right()
You can build a tree like this:
print AndNode(Leaf(True), Leaf(False))()
print AndNode(OrNode(Leaf(True), Leaf(False)), Leaf(True))()
Which outputs this:
False
True

Categories

Resources