2016-06-28 10 views
8

Also, ich beobachtete Raymond Hettinger's Gespräch Transforming Code into Beautiful, Idiomatic Python und er bringt diese Form von iter, die ich nie bewusst war. Sein Beispiel ist die folgende:Was sind die Verwendungen von iter (aufrufbar, Sentinel)?

Statt:

blocks = [] 
while True: 
    block = f.read(32) 
    if block == '': 
     break 
    blocks.append(block) 

Verwendung:

blocks = [] 
read_block = partial(f.read, 32) 
for block in iter(read_block, ''): 
    blocks.append(block) 

Nach Überprüfung der documentation von iter, fand ich ein ähnliches Beispiel:

with open('mydata.txt') as fp: 
    for line in iter(fp.readline, ''): 
     process_line(line) 

Diese Sieht für mich ziemlich nützlich aus, aber ich habe mich gefragt, ob von dir Pythonis kennen Sie irgendwelche Beispiele dieses Konstrukts, die keine I/O-Leseschleifen beinhalten? Vielleicht in der Standardbibliothek?

ich sehr gekünstelt Beispiele denken kann, wie folgt aus:

>>> def f(): 
...  f.count += 1 
...  return f.count 
... 
>>> f.count = 0 
>>> list(iter(f,20)) 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 
>>> 

Aber offensichtlich ist dies nicht mehr sinnvoll, dass die eingebaute in Iterables. Außerdem scheint es für mich Code-Geruch zu sein, wenn Sie einer Funktion einen Status zuweisen. An diesem Punkt sollte ich wahrscheinlich mit einer Klasse arbeiten, aber wenn ich eine Klasse schreibe, könnte ich genauso gut das Iterator-Protokoll für alles implementieren, was ich erreichen möchte.

+2

Für Menschen, die die Frage oder stimmten Downvoted zu schließen, würde ich ein Feedback, wie schätzt besser diese Frage zu stellen. –

Antwort

4

In der Regel sind die wichtigsten Anwendungen ich habe für zwei arg iter gesehen beinhalten Umwandlung Funktionen, die C-APIs (impliziter Zustand, kein Konzept der Iteration) zu Iteratoren ähneln. Dateiähnliche Objekte sind ein häufiges Beispiel, aber es zeigt sich in anderen Bibliotheken, die C-APIs schlecht wickeln. Das Muster, das Sie erwarten würden, wäre eines in APIs wie FindFirstFile/FindNextFile, in dem eine Ressource geöffnet ist und jeder Aufruf den internen Status weiterleitet und einen neuen Wert oder eine Markervariable zurückgibt (wie NULL in C). Es ist normalerweise am besten, es in einer Klasse zu implementieren, die das Iteratorprotokoll implementiert, aber wenn Sie es selbst machen müssen, während die API ein C-Level ist, kann das Wrapping die Verwendung verlangsamen, wobei zwei Argumente in C as implementiert werden Nun, kann die Kosten für zusätzliche Byte-Code-Ausführung vermeiden.

Andere Beispiele beinhalten veränderliche Objekte, die nur einmal die Verarbeitung abgeschlossen ist während der Schleife selbst, beispielsweise Looping in umgekehrter Reihenfolge über die Leitungen in einem bytearray, das Entfernen der Zeile geändert werden:

>>> from functools import partial 
>>> ba = bytearray(b'aaaa\n'*5) 
>>> for i in iter(partial(ba.rfind, b'\n'), -1): 
...  print(i) 
...  ba[i:] = b'' 
... 
24 
19 
14 
9 
4 

Ein anderer Fall ist, wenn B. eine effiziente (falls zugegeben hässliche) Art und Weise zu verwenden, eine iterierbare Gruppe in Gruppen von n Elementen zu gruppieren, während die letzte Gruppe weniger als n Elemente erlaubt, wenn die iterierbare Eingabe kein geradzahliges Vielfaches von n ist Elemente in der Länge (dieses habe ich tatsächlich verwendet, obwohl ich normalerweise itertools.takewhile(bool anstelle von zwei Arg 012 verwende):

# from future_builtins import map # Python 2 only 
from itertools import starmap, islice, repeat 

def grouper(n, iterable): 
    '''Returns a generator yielding n sized tuples from iterable 

    For iterables not evenly divisible by n, the final group will be undersized. 
    ''' 
    # Keep islicing n items and converting to groups until we hit an empty slice 
    return iter(map(tuple, starmap(islice, repeat((iter(iterable), n)))).__next__,()) # Use .next instead of .__next__ on Py2 

Eine andere Verwendung: mehrere in Essig eingelegte Objekte in einer einzigen Datei von einem Sentinel-Wert (None zum Beispiel gefolgt Schreiben,), so dass, wenn Unpickling Sie dieses Idiom statt, um irgendwie die Zahl zu erinnern, verwenden können, um bis EOFError von Gegenständen gebeizt, oder müssen load immer und immer wieder nennen:

with open('picklefile', 'rb') as f: 
    for obj in iter(pickle.Unpickler(f).load, None): 
     ... process an object ... 
+0

Danke für den Hintergrund hinsichtlich der Konvertierung von Funktionen ähnlich wie C APIs, das ist genau das, was ich gesucht habe. –

8

Hier ist ein dummes Beispiel kam ich mit:

from functools import partial 
from random import randint 

pull_trigger = partial(randint, 1, 6) 

print('Starting a game of Russian Roulette...') 
print('--------------------------------------') 

for i in iter(pull_trigger, 6): 
    print('I am still alive, selected', i) 

print('Oops, game over, I am dead! :(') 

Beispielausgabe:

$ python3 roulette.py 
Starting a game of Russian Roulette... 
-------------------------------------- 
I am still alive, selected 2 
I am still alive, selected 4 
I am still alive, selected 2 
I am still alive, selected 5 
Oops, game over, I am dead! :(

Die Idee ist, einen Generator zu haben, die Zufallswerte liefert, und Sie möchten einmal ein Verfahren ein Ein bestimmter Wert wurde ausgewählt. Sie könnten z.B. Verwenden Sie dieses Muster in jedem Durchlauf einer Simulation, die versucht, das durchschnittliche Ergebnis eines stochastischen Prozesses zu bestimmen.

Natürlich ist der Prozess, den Sie Modellierung wahrscheinlich viel sein würde wäre komplizierter unter der Haube als ein einfacher Würfelwurf ...

Ein weiteres Beispiel, das ich von würde denken kann wiederholt eine Operation durchführen, bis es gelingt, angezeigt durch eine leere Fehlermeldung (lassen Sie uns gerade hier davon ausgehen, dass einige 3rd-Party-Funktion wie die statt zB mit Ausnahmen ausgelegt ist):

from foo_lib import guess_password 

for msg in iter(guess_password, ''): 
    print('Incorrect attempt, details:', msg) 

# protection cracked, continue... 
+0

Ich hätte an eine Funktion gedacht, die zufällige Werte selbst zurückgibt! –

Verwandte Themen