2016-07-14 36 views
1

一旦一个zip元素已经建成,比方说从两个列表,跟踪该ID所构建的拉链

z = zip(l1, l2) 

有从z拿到构建l1l2清单ID的方法,或者是z完全不知道它的起源?

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

+3

什么是你想用这个信息来解决实际问题? – jonrsharpe

+1

有没有办法摆脱'z'这些ID(其实,有没有保证'l1'和'l2'在你的程序以后的某个点仍然存在,即使'z'仍然如此 - 在这种情况下, “id”甚至可能是完全不同对象的ID ......)。你为什么要这样? – mgilson

+0

'id'是什么意思?不,[文档](https://docs.python.org/3.5/library/functions.html#zip)似乎是另有说明。请注意它们提供的等效代码。 –

回答

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的元组是优化的一部分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] 

我们可以检索列表。

+0

哦精灵!我完全不需要那个*包装类* –

+0

这非常棒。 – Aguy

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。