Why does this instance variable never assume False value?

0

When running the following code, the variable _order_stability never gets False, even when I try to force it during the debug.

The variable can assume other values, for example of type int that are different from 0 and 1.

When I run the code, the first line of the insert function of the RandomAccessLinkedList class tries to change the value of the unsuccessful variable.

I am using Python 3.5.2 (default) in linux, but the error also happens in windows.

from collections import Sequence


class Node:
    def __init__(self, value):
        self.value = value
        self._next = None

    @property
    def next(self):
        return self._next

    @next.setter
    def next(self, next_node):
        self._next = next_node

    def __str__(self):
        return repr(self.value)

    def __repr__(self):
        return str(self.value)


class RandomAccessLinkedList(Sequence):
    def __init__(self, *valores):
        self._head = Node(valores[0])
        self._tail = Node(valores[0])

        self._order_stability = True
        self._change_point = None

        nodo_previous = self._head
        for value in valores[1::]:
            nodo = Node(value)
            nodo_previous.next = nodo
            self._tail = nodo
            nodo_previous = nodo

        self._data = [Node(item) for item in valores]

    @property
    def data(self):
        if self._order_stability:
            return self._data

        counter = len(self._data)

        start = 0
        nodo_atual = self._head
        if self._change_point is not None:
            start = self._change_point
            nodo_atual = self._data[start]
            self._change_point = None

        for i, j in enumerate(range(start, counter)):
            self._data[i] = nodo_atual
            nodo_atual = nodo_atual.next

        self._order_stability = True

        return self._data

    def next(self):
        pass

    def insert(self, new_value, index):
        self._order_stability = False
        self._change_point = index
        self._data.append(None)

        new_value = Node(new_value)

        if index > 0:
            previous = self._data[index-1]

            pivo = previous.next
            previous.next = new_value
            new_value.next = pivo
        elif index == 0:
            new_value.next = self._data[0]
            self._head = new_value
        elif index == len(self._data)-2:
            self._order_stability = True
            self._change_point = None
            self._data[-1] = new_value

    def __getitem__(self, index):
        return self.data[index].value

    def __len__(self):
        return len(self.data)

    def __repr__(self):
        return repr(self.data)

    def __str__(self):
        string = 'Ø → {}'
        string += ' → {}' * (len(self.data) - 1)
        string += ' → Ø'
        return string.format(*[i.value for i in self.data])

    def __eq__(self, outra_lista):
        if id(self) == id(outra_lista):
            return True
        if len(outra_lista) != len(self):
            return False
        for i, j in enumerate(outra_lista):
            if j != self[i]:
                return False
        return True


if __name__ == '__main__':
    lista = RandomAccessLinkedList(*[i for i in range(5)])
    lista.insert(5, 0)

Where is my error?

    
asked by anonymous 25.10.2016 / 02:57

1 answer

3

Your __eq__ calls len (self) which in turn uses prperty data that resets order_stability - since you detected the problem in the IDE, which may be necessitating IDE to be comparing the its object implicitly, apra make the introspections of it, and that causes the change of state.

Ideally, verifying equality should not trigger code that modifies the object - a simple local modification would be to use len (self._data) and not len (self.data) in its __len__ . But that would not be the best design there: The best is perhaps to trigger the ordering in a "sync" manner, at the end of insert - and not, leave it archived in the _order_stability flag as you want - (this prevents read accesses from modifying the object) - if lazy design it's okay to keep it that way - but then do not rely on IDE that fz introspections automatically fork the right thing.

Another suggestion is to check collections.abc and inherit your MutableSequence class - from that automatically forms all the expected methods of a sequence will be available, and will trigger the reordering trigger when you need it.

    
26.10.2016 / 14:31