2015-05-21 12 views
5
def partition(n, iterable): 
    p = izip_longest(*([iter(iterable)] * n)) 
    r = [] 
    for x in p: 
     print(x) #I added this 
     s = set(x) 
     s.discard(None) 
     r.append(list(s)) 
    return r 

Dies ist eigentlich in einer Stellenausschreibung auf SO und ein Neuling zu sein, dachte ich, dass es interessant war. So erhalten Sie eine Ausgabe wie folgt aus:Was macht diese Funktion? (Python iterators)

partition(5, L) 
(1, 2, 3, 4, None) 
Out[86]: [[1, 2, 3, 4]] 

Für mich ist das schon verwirrend, weil ich dachte izip_longest(*([iter(iterable)] * n)) die izip_longest Funktion auf einer Liste von n identischen Iteratoren laufen würde, so würde ich zum ersten Mal eine Ausgabe von (1,1,1,1,1) erwartet haben und dann eine Ausgabe von (2,2,2,2,2) und so weiter.

So kurze Version meiner Frage ist, was mit dieser Linie los ist:

p = izip_longest(*([iter(iterable)] * n)) 

es Parsing ich gedacht hätte [iter (abzählbaren)] * n erstellt eine Liste der Länge n von identischen Iterables all auf dasselbe zeigen - das ist es, was es in der Befehlszeile tut, aber das scheint nicht zu sein, was es hier tut, basierend auf der oben gedruckten Ausgabe.

Auch ich dachte der * zu Beginn ...longest(*... war da, da die Liste von unbekannter Länge ist aber ich denke nicht, dass das völlig Sinn macht. Was macht das erste * Symbol innerhalb des Funktionsaufrufs? Scheint nicht so, als würde es einfach eine unbekannte Länge Liste von Argumenten anzeigen ...

Also am Ende des Tages bin ich völlig verloren. Kann mir jemand diese Syntax erklären?

Vielen Dank für jede Eingabe!


Vielen Dank für alle hilfreiche Antworten, alle. Ich bin mir nicht sicher, ob ich hier eine Antwort oder eine Frage anwende, aber es scheint mir, dass dieses Listenverständnis dasselbe für Listen und Tupel tun wird (ich realisiere, dass Iteratoren auch für Wörterbücher, benutzerdefinierte Klassen, andere Dinge gelten würden). .

) wandelt
[L[i*n:(i+1)*n] for i in range(int(ceil(len(L)/float(n)))) ] 
+1

Haben Sie lesen [Wie funktioniert 'zip (* [iter (s)] * n)' Arbeit in Python] (http://stackoverflow.com/questions/2233204/how- does-zipitersn-Arbeit-in-Python)? –

+0

es bricht eine große Liste in N Größe kleinere Listen .... filling Keine für den Fall, dass die Listenlänge nicht gleichmäßig durch N teilbar ist ... die einzige Unterliste, die keine 'None 'enthalten sollte, ist die letzte Liste –

+0

Hinzufügen a 'print (list (p))', um zu sehen, was 'izip_longest()' getan hat. – martineau

Antwort

6

Gegeben vereinfachen könnten:

>>> li 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] 

Es gibt eine Gemeinsames Python-Idiom der Verwendung von zip in Kombination mit iter und * operator zum Partitionieren einer Liste einer flachen Liste in eine Liste von Listen mit n Länge:

>>> n=3 
>>> zip(*([iter(li)] * n)) 
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14), (15, 16, 17), (18, 19, 20)] 

Wenn jedoch n kein gerades Vielfaches der Gesamtlänge wird die endgültige Liste abgeschnitten:

>>> n=4 
>>> zip(*([iter(li)] * n)) 
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14, 15), (16, 17, 18, 19)] 

Sie izip_longest können Sie die vollständige Liste mit einem gewählten Wert ausgefüllt verwenden für die unvollständigen Teillisten:

>>> list(izip_longest(*([iter(li)] * n))) 
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14, 15), (16, 17, 18, 19), (20, None, None, None)] 
+0

gute Antwort auf die Erklärung, warum er bekam keine und warum es mit izip_longest :) +1 –

+0

@dawg danke viel. Das ist wirklich nett. – sunny

+1

Es sollte beachtet werden, dass als Folge der Art und Weise, in der die zusätzlichen 'None' entfernt werden, diese Iterables, die' None' enthalten, von dieser Funktion nicht unterstützt werden. Zum Beispiel ergibt "partition (2, [1,2, None, 4,5])" '[[1, 2], [4], [5]]'. Es wäre robuster gewesen, einen benutzerdefinierten Sentinel-Wert zu verwenden, denke ich. – jpmc26

6

iter(my_list) eine Liste in eine iterable (das ist eine, wo Elemente verbraucht werden, wie sie)

[my_iter]*5 erstellt eine neue Liste von [my_iter,my_iter,my_iter,my_iter,my_iter] in dem alle my_iter ‚s auf die gleiche gesehen werden genauer Iterator

zip(*[my_iter,my_iter,my_iter,my_iter,my_iter]) 

ist die gleiche wie

zip(my_iter,my_iter,my_iter,my_iter,my_iter) 

(das Splat auspackt einfach eine Liste/Tupel), die im Grunde genommen gibt nur eine 5xlen(my_list)//5 2d Liste

Sie es mit normaler Zip

#this method will have no `None` entries 
new_list_partitioned = zip(*[iter(big_list)]*N) + [big_list[-(len(big_list)%N):],] 
+0

Wenn Sie auf meine Frage schauen, habe ich diesen Teil bekommen. Was ich nicht bekam war, warum das * vor [ier (... – sunny

+0

es entpackt die Liste ... –