Implementing linked list from scratch - Follow up
Specification and Unit Tests


You are lacking a clear specification for your methods. We have to guess what these methods do exactly, specially for edge cases.
You should provide unit tests when providing an API class. You would have found some bugs if you did.


Review


 @head.setter
    def head(self, node):
        if node is not None:
            self.__head = node



There is no link from the new head to the previous one. Also, what would you do if node.next is already filled?

 @head.setter
    def head(self, node):
        if node is not None:
            node.next = self.__head
            self.__head = node





@tail.setter
    def tail(self, node):
        if node is not None:
            try:
                if node.next is None:
                    self.__tail.next = node
                    self.__tail = self.__tail.next
            except AttributeError:
                self.__tail = node



Why would you expect an AttributeError here? You are only setting next. And why would you ignore a tail that has a next node? Why not include the tail chain?




''' generator for nodes '''
''' iterating, search etc. '''
def node_generator(self, target=None):
    node = self.head
    yield node
    while node.next is not None and node.next.key != target:
        node = node.next
        yield node



The spec is unclear here. You always include the head, and then continue as long as a next node's key does not match the specified target. Why not check head for the same condition?




def delete(self, target):
    for node in self.node_generator(target):
        pass
    node.next = node.next.next
    self.length -= 1



What if the node you want to delete is the tail? This edge case is not foreseen.