Why does this instance variable never take False value?

Asked

Viewed 159 times

1

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

The variable can take other values, for example of the type int other than 0 and 1.

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

I’m using Python 3.5.2 (default) on linux, but the error happens also 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 mistake?

  • Friend I believe your error is in the declaration of the date property, right in the first line you check if the _order_stability variable is True and returns the self. _data, but note that soon at the initialization of your class you already initialize the variable with True. There might be something wrong with this part. Another thing is that it may also be generating some infinite loops in function statements Len(self) which is returning the length of the property and not the variable, check the references to self.data and self. _data.

  • Remember that access to self.data triggers the getter function defined in the date and self property. _data accesses the internal variable. I suggest reviewing the uses of the variable.

  • The problem is that Insert cannot change the value from True to False in the _order_stability variable. Neither forcing the True value during debug changes the variable.

  • 1

    Change it changes, see https://repl.it/EFIT/1

  • Maybe the problem is in the IDE so... thanks @stderr

  • Actually, the error occurs in the IDE, and only during debug.

Show 1 more comment

1 answer

4


Your __eq__ calls Len(self) which in turn uses prperty data that resets the order_stability - since you have detected the problem in the IDE, what may be happening is that the IDE is comparing its object implicitly, in order to make its insights, and this causes the change of state.

Ideally, checking equality should not triggate 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 wouldn’t be the best design there: Perhaps the best is to fire the ordination so "synchronous, at the end of the insert - and not, leave it on the flag of _order_stability how do you want - (this prevents read accesses from modifying the object) - if the Lazy design is realmetne desired, it’s okay to keep it that way - but then don’t count on the IDE that’s automatically introduced.

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

  • Lazy was purposeful, using the Property serves to ensure that the object is up-to-date. In the current version, the first call of a method is always by Property, and the subsequent by variable. How they work/what are these insights?

  • 1

    These insights are taken up by the IDE itself, and there is no way of knowing when and how they are done - it is best to assume that you cannot ra'rely on the "auto-complete" feature of such a die for this type of code, (which generates side effects in consuta a properties, for example). } Batsa use tool otura to write your code, and use inteerative sessions and tests to track how it is getting, rather than relying on the automatic IDE.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.