在此示例代码中了解ctypes模块的用法

时间:2018-11-24 05:55:43

标签: python python-3.x linked-list ctypes

上下文:
我发现一些实现XOR链表的代码。在XOR链表中,它不是每个节点都有下一个指针,而是具有both属性,它是上一个节点和下一个节点的XOR。

import ctypes


# This is hacky. It's a data structure for C, not python.
class Node(object):
    def __init__(self, val):
        self.val = val
        self.both = 0


class XorLinkedList(object):
    def __init__(self):
        self.head = self.tail = None
        self.__nodes = [] # This is to prevent garbage collection

    def add(self, node):
        if self.head is None:
            self.head = self.tail = node
        else:
            self.tail.both = id(node) ^ self.tail.both
            node.both = id(self.tail)
            self.tail = node

        # Without this line, Python thinks there is no way to reach nodes between
        # head and tail.
        self.__nodes.append(node)


    def get(self, index):
        prev_id = 0
        node = self.head
        for i in range(index):
            next_id = prev_id ^ node.both

            if next_id:
                prev_id = id(node)
                node = _get_obj(next_id)
            else:
                raise IndexError('Linked list index out of range')
        return node


def _get_obj(id):
    return ctypes.cast(id, ctypes.py_object).value

问题:

  1. 不了解_get_obj()函数的需要以及正在尝试的功能 在这里做什么?
  2. self.__nodes = []有什么用?以及它是如何实现的 垃圾收集在这里吗?
  3. 我不知道以下代码在做什么:

    # Without this line, Python thinks there is no way to reach nodes between
    # head and tail.
    self.__nodes.append(node)`
    

1 个答案:

答案 0 :(得分:1)

我可以回答您问题中的大部分子问题。

  1. _get_obj()函数是Python本身的id()逆函数(无论如何都具有CPython解释器)。 还有其他方法可以做到这一点。例如,请参见问题Is it possible to dereference variable id's?

  2. &3。self.__nodes.append(node)Node实例添加到私有列表中,因为将其添加到XOR链接列表中并不会创建对该引用的引用,更常见的常规实现(XOR技巧消除了对它们的需求)。没有这个,Python垃圾收集器可能会删除Node实例,而该实例仍然是链表的一部分。