跟踪构成zip的id

时间:2016-07-14 21:32:44

标签: python python-3.x

一旦构建了一个zip元素,比如两个列表,

z = zip(l1, l2)

是否有方法可以从z获取构建l1l2列表的ID,或z完全不了解其来源?

我没有找到任何看似相关的方法,但也许......

2 个答案:

答案 0 :(得分:3)

在有限的情况下,理论上可行。您可能希望在交互模式或pdb调试会话中执行此类操作,如果它是获取您忘记引用的对象的唯一方法,但它不是某些内容你应该在一个程序中使用。

让我们来看看zip迭代器向垃圾收集器报告的引用:

>>> import gc
>>> gc.get_referents(zip([1], [2]))
[(<list_iterator object at 0x7fcb4764dcf8>, <list_iterator object at 0x7fcb4764dbe0>), (None, None)]

我们看到对两个底层迭代器的元组的引用,以及None的元组。 None s的元组是优化zip的一部分,用于节省分配输出元组的时间。这对我们来说并不感兴趣。 list_iterator对象更有趣,但是你要求列表,而不是列表迭代器。

列表上的迭代器需要保持对列表的引用,并且由于此引用可能涉及引用循环,因此列表迭代器需要在请求时将此引用报告给垃圾收集器。因此,如果我们再次使用gc.get_referents

>>> z = zip([1], [2])
>>> gc.get_referents(z)
[(<list_iterator object at 0x7fcb4764db70>, <list_iterator object at 0x7fcb4764dd30>), (None, None)]
>>> l_iters = _[0]
>>> gc.get_referents(l_iters[0])[0]
[1]
>>> gc.get_referents(l_iters[1])[0]
[2]

我们可以检索列表。

答案 1 :(得分:0)

zip不提供您所寻求的功能。

您可以创建一个提供此功能的包装类

class Zip:

    def __init__(self, func=zip):
        self.ids = None
        self.func = func

    def __call__(self, *args):
        self.ids = [id(a) for a in args]
        return self.func(*args)

可以这样使用:

>>> z = Zip()
>>> l1 = [1, 2, 3, 4, 5]
>>> l2 = ['a', 'b', 'c', 'd', 'e']
>>> list(z(l1, l2))
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]
>>> z.ids
[52203152, 52334640]

但是,我们无法保证在您的代码中稍后的某些时候,原始列表对象仍然拥有这些ID。