L.P. L.P. - 1 month ago 7
Python Question

Calling the function 'list(...)' directly on a created class

I am aware that within the Python Class creation one could overload some specific functionalities, so that when some of pythons build in functions are called on the created object they are able to act properly on them ie.

class Node(object):
def __init__(self, contents=None,leftNode=None, rightNode=None):
super(Node, self).__init__()
self.__leftNode = leftNode
self.__rightNode= rightNode
self.__contents = contents

# OverLoad the str function. Prints the address of the Node, and it's contents.
def __str__(self):
addr=repr(self).split(' ')[-1][:-1]
return str('Addr: {0}\tContents: {1}'.format(addr, self.__contents))


This allows pretty printing of the data that is output when print or str(...) is called on the node object. What I would like to know is if there is a way to do the same for list(...) where in, if I were to pass a Linked List object that was implemented, it would be able to return a python list implementation, which would just append all of the nodes contents to a list, and return it. I know this sounds somewhat simple, and unneeded, but about to produce a Binary Tree Class implementation, and would like to be able to produce a Heap Sort Able list in itself. If clarification of any of this is needed, I'll probably be quick to reply. I tried to implement the iter property, but just went about creating a weird s***show of an infinite loop, unrelated to this but... yeah.

Thanks to @Leva7 got this done properly within the linkedList class, moving to Binary Tree Heap Sort.
Implementation:

def __iter__(self):
if self.isEmpty():
return
self.walkList(self.__maxNegIndex)
while True:
yield self.getContent()
if self.getNode(self.right) is None:
break
self._Node=self.getNode(self.right)


Sample Use Case:

>>> q=DoublyLinkedList(0)
>>> for i in range(1,10):
... q.addToLeft(i)
... q.addToRight(-i)
...
>>> q.printList()
Index: -9 Element: 9
Index: -8 Element: 8
Index: -7 Element: 7
Index: -6 Element: 6
Index: -5 Element: 5
Index: -4 Element: 4
Index: -3 Element: 3
Index: -2 Element: 2
Index: -1 Element: 1
Index: 0 Element: 0
Index: 1 Element: -1
Index: 2 Element: -2
Index: 3 Element: -3
Index: 4 Element: -4
Index: 5 Element: -5
Index: 6 Element: -6
Index: 7 Element: -7
Index: 8 Element: -8
Index: 9 Element: -9
>>> list(q)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
>>>

Answer

This is done by implementing the __iter__ method. The list constructor will use it to iterate over your object and create a list from that. Keep in mind that it should be a generator method, rather than returning a list.

Example:

class Test:
    def __iter__(self):
        for i in range(5):
            yield i

ls = list(Test())
print(ls)

The output will be:

[0, 1, 2, 3, 4]

In your case, you would take the first node, and until the end (which is somehow marked in your implementation) you yield the next node, so something like that:

def __iter__(self):
    curr_node = self
    while curr_node.__not_last:
        yield curr_node.__contents
        curr_node = curr_node.__rightNode

And for that you need a __not_last boolean property in the Node object