2016-07-14 6 views
1

Sobald ein Zip-Element konstruiert wurde konstruiert, sagen wir zum Beispiel aus zwei Listen,die ids Trace, die einen Reißverschluss

z = zip(l1, l2) 

ein Verfahren Gibt es von z die ids der Konstruktion l1 und l2 Listen zu bekommen, oder ist z völlig unbekannt über seinen Ursprung?

ich keine Methode gefunden haben, die relevant erscheinen, aber vielleicht ...

+3

Was ist das eigentliche Problem, das Sie versuchen, mit diesen Informationen zu lösen? – jonrsharpe

+1

Es gibt keine Möglichkeit, diese IDs von 'z' zu erhalten (in der Tat gibt es keine Garantie, dass' l1' und 'l2' zu einem späteren Zeitpunkt in Ihrem Programm noch existieren, auch wenn' z' das immer noch tut - in diesem Fall die 'id' könnte sogar die IDs von völlig verschiedenen Objekten sein ...). Warum willst du das? – mgilson

+0

Was meinst du mit 'id'? Und nein, [die Dokumentation] (https://docs.python.org/3.5/library/functions.html#zip) scheint etwas anderes zu bedeuten. Notieren Sie den entsprechenden Code, den sie bereitstellen. –

Antwort

3

Es ist theoretisch in begrenzten Fällen möglich. Vielleicht möchten Sie etwas im interaktiven Modus oder in einer pdb Debugging-Sitzung tun, wenn dies die einzige Möglichkeit ist, an ein Objekt heranzukommen, das Sie vergessen haben, einen Verweis zu behalten, aber das ist nichts, was Sie jemals in einem Programm verwenden sollten.

Werfen wir einen Blick darauf werfen, was verweist auf eine zip Iterator Berichte an den Garbage Collector:

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

Wir Verweise auf ein Tupel von zwei zugrunde liegenden Iteratoren zu sehen, und ein Tupel von None s. Das Tupel von None s ist Teil einer Optimierung zip verwendet, um Zeit bei der Zuweisung von Ausgangstupel zu sparen. Es ist für uns nicht interessant. Die list_iterator Objekte sind interessanter, aber Sie haben nach den Listen gefragt, nicht nach Iteratoren.

Ein Iterator über einer Liste muss einen Verweis auf die Liste behalten, und da dieser Verweis in einem Referenzzyklus enthalten sein kann, muss der Listeniterator diesen Verweis bei Aufforderung an den Garbage Collector melden. Wenn wir also gc.get_referents wieder verwenden:

>>> 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] 

Wir haben die Listen abrufen können.

+0

Oh Sprite! Ich würde das * Wrapper-Klasse * schließlich nicht brauchen –

+0

Das ist ziemlich genial. – Aguy

0

zip bietet keine Funktionalität, die Sie suchen.

Sie stattdessen eine Wrapper-Klasse erstellen könnte, die diese Funktionalität bietet:

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) 

Und kann verwendet werden, wie zum Beispiel:

>>> 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] 

Allerdings gibt es keine Garantie, dass einige später an In Ihrem Code zeigen die ursprünglichen Listenobjekte diese IDs noch an.

Verwandte Themen