一旦构建了一个zip元素,比如两个列表,
z = zip(l1, l2)
是否有方法可以从z
获取构建l1
和l2
列表的ID,或z
完全不了解其来源?
我没有找到任何看似相关的方法,但也许......
答案 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。