oDium - 1 year ago 54

Python Question

Situation: I'm trying to get a good handle on the doubly-linked structure. I've got a decent grip on the methods so far. I want to be able to create two objects for this class and check if every item in it is equal. I don't have any syntax errors, and the error I'm getting is kind of confusing. So here's what I have so far.

`class LinkedList:`

class Node:

def __init__(self, val, prior=None, next=None):

self.val = val

self.prior = prior

self.next = next

def __init__(self):

self.head = LinkedList.Node(None) # sentinel node (never to be removed)

self.head.prior = self.head.next = self.head # set up "circular" topology

self.length = 0

def append(self, value):

n = LinkedList.Node(value, prior=self.head.prior, next=self.head)

n.prior.next = n.next.prior = n

self.length += 1

def _normalize_idx(self, idx):

nidx = idx

if nidx < 0:

nidx += len(self)

if nidx < -1:

raise IndexError

return nidx

def __getitem__(self, idx):

"""Implements `x = self[idx]`"""

nidx = self._normalize_idx(idx)

currNode = self.head.next

for i in range(nidx):

currNode = currNode.next

if nidx >= len(self):

raise IndexError

return currNode.val

def __setitem__(self, idx, value):

"""Implements `self[idx] = x`"""

nidx = self._normalize_idx(idx)

currNode = self.head.next

if nidx >= len(self):

raise IndexError

for i in range(nidx):

currNode = currNode.next

currNode.val = value

def __iter__(self):

"""Supports iteration (via `iter(self)`)"""

cursor = self.head.next

while cursor is not self.head:

yield cursor.val

cursor = cursor.next

def __len__(self):

"""Implements `len(self)`"""

return self.length

def __eq__(self, other):

currNode = self.head.next

currNode2 = other.head.next

for currNode, currNode2 in zip(self, other):

if currNode.val != currNode2.val:

return False

return True

Test:

`from unittest import TestCase`

tc = TestCase()

lst = LinkedList()

lst2 = LinkedList()

tc.assertEqual(lst, lst2)

lst2.append(100)

tc.assertNotEqual(lst, lst2)

When I test this code I get I get an Assertion error saying "

`[] == [100]`

Answer Source

`zip`

only goes as far as the shortest list. You want `itertools.zip_longest`

, and you don't want `.val`

(your iterator returns the actual values already). Try this:

```
def __eq__(self, other):
for val1, val2 in zip_longest(self, other):
if val1 != val2:
return False
return True
```

or perhaps better?

```
def __eq__(self, other):
return all(val1 == val2 for val1, val2 in zip_longest(self, other))
```

**EDIT**

I like @BrenBarn's suggestion of checking length first. Here's a more efficient answer:

```
def __eq__(self, other):
return len(self) == len(other) and all(
val1 == val2 for val1, val2 in zip(self, other))
```