<\/HEAD>
Dies ist der zweite Teil einer mehrteiligen Serie über ArcPy-Cursor; insbesondere die Arbeit mit ArcPy-Cursorn als iterierbare Objekte in Python. Der erste Teil der Serie<\/A> behandelt einige der wichtigen Komponenten der Iteration in Python. Der zweite Teil der Serie<\/STRONG> beschäftigt sich mit dem Iterieren und Schleifen über ArcPy Data Access Cursorn. Der dritte Teil der Serie <\/A>behandelt die Verwendung mehrerer Python Built-in- und itertools-Funktionen mit ArcPy Data Access Cursorn. Der vierte Teil der Serie wird sich mit der Verwendung von Generatoren oder Generator-Ausdrücken befassen, um Auswahl- oder Filterlogik für die Wiederverwendung von Code zu trennen. Fünfte oder folgende Teile sind derzeit unbekannt.<\/EM><\/P><\/P>
Der erste Teil dieser Serie ist für einige ArcPy-Skripter wahrscheinlich etwas akademisch, aber ich glaube, ein wenig Theorie hilft sehr beim Verständnis der Praxis von etwas, in diesem Fall der Arbeit mit ArcPy Data Access Cursorn auf idiomatische Weise. Außerdem werden die im ersten Beitrag dargelegten Begriffe und Konzepte immer wieder in der gesamten Serie auftauchen.<\/P>
<\/P>
Bevor wir weitermachen, möchte ich auf eine Präsentation von vor einigen Jahren hinweisen:
Loop Like A Native<\/A>. Ned Batchelder <\/A>gibt einen schönen Überblick über das Schleifen in Python, besonders für diejenigen mit Schleifenerfahrung in anderen Programmiersprachen. Es hat einige Male gedauert, bis ich die ganze Präsentation verstanden habe, aber sie hat wirklich meine Sichtweise auf Iterieren und Schleifen in Python verändert.<\/P><\/P>
Wir verwenden erneut die Python-Liste und ArcPy-Cursor-Beispiele aus dem vorherigen Beitrag und rufen iter()<\/SPAN> auf, um einen Iterator zurückzugeben, mit dem man manuell durch jedes Iterable gehen kann.<\/P>>><\/SPAN>><\/SPAN> #Erstelle Liste, hänge 2 Iteratoren an und rufe Werte ab durch<\/SPAN>
>><\/SPAN>><\/SPAN> # Aufruf von next() und object.next()<\/SPAN>
>><\/SPAN>><\/SPAN> l =<\/SPAN> [<\/SPAN>10<\/SPAN>,<\/SPAN> 20<\/SPAN>,<\/SPAN> 30<\/SPAN>,<\/SPAN> 40<\/SPAN>,<\/SPAN> 50<\/SPAN>]<\/SPAN>
>><\/SPAN>><\/SPAN> it_l =<\/SPAN> iter(<\/SPAN>l)<\/SPAN>
>><\/SPAN>><\/SPAN> it2_l =<\/SPAN> iter(<\/Span>l)<\span>
>><\span>><\span> print next(it_l), next(it2_l)
10 10
>> > print it_l.next(), it2_l.next()
20 20
>> >
>> > #Erstelle SearchCursor, hänge 2 Iteratoren an und rufe Werte ab durch
>> > # Aufruf von next und object.next()
>> > cur = arcpy.da.SearchCursor(fc, ["OID@", "SHAPE@"])
>> > it_cur = iter(cur)
>> > it2_cur = iter(cur)
>> > print next(it_cur), next(it2_cur)
(1, ) (2, )
>> > print it_cur.next(), it2_cur.next()
(3, ) (4, )
>> > print next(cur)
(5, )
>> >
<<EMOJI_0></span><<EMOJI_1></span><<EMOJI_2></span><<EMOJI_3></span><<EMOJI_4></span><<EMOJI_5></span><<EMOJI_6></span><<EMOJI_7></span><<EMOJI_8></span><<EMOJI_9></span><<EMOJI_10></span><<EMOJI_11></span><<EMOJI_12></span><<EMOJI_13></span><<EMOJI_14></span><<EMOJI_15></span><<EMOJI_16></span><<EMOJI_17></span><<EMOJI_18></span><<EMOJI_19></span><<EMOJI_20></span><<EMOJI_21>
Es gibt einiges zum obigen Code zu kommentieren:
- Ein einzelnes Iterable kann gleichzeitig von mehreren Iteratoren angesprochen werden. Wie sich das Iterable bei mehreren Iteratoren verhält, ist implementierungsspezifisch.
Iterators<\A> im Python Glossar, eine Liste "erzeugt bei jedem Aufruf der Funktion iter() oder bei Verwendung in einer for-Schleife einen neuen frischen Iterator." Dies erklärt, warum die Zeilen 06-07 und 08-09 für beide Iteratoren dieselben Werte ausgeben.<\/LI>Im Gegensatz zur Python-Liste erzeugt der ArcPy Data Access SearchCursor keinen neuen Iterator, d.h. jeder nachfolgende Aufruf der Funktion iter() gibt dasselbe Iteratorobjekt zurück, das bereits verwendet wird. In solchen Fällen bewegt jeder Aufruf von next() den Iterator um ein Element weiter, unabhängig davon, welcher Iterator den Aufruf tätigt. Dies erklärt, warum die Zeilen 16-17 die erste und zweite OID anzeigen, anstatt die erste OID zweimal zu zeigen.<\/LI><\/UL><\/LI>Ein Iterator kann entweder mit der eingebauten Funktion next() oder mit der next-Methode des Objekts vorwärts bewegt werden. Ab Python 3.0, mit der Einführung von PEP 3114, ist die bevorzugte Methode zum manuellen Iterieren die eingebaute Funktion next().<\/LI>Da ArcPy Data Access Cursors ihre eigenen Iteratoren sind, muss man nicht iter() aufrufen, um ein Iteratorobjekt zu erhalten, bevor man next() aufruft. Zeile 20 zeigt, dass das Cursorobjekt selbst an next() übergeben werden kann, um das nächste Element abzurufen und den Cursor vorwärts zu bewegen.<\/LI><\/UL><\/P>Glücklicherweise übernimmt die Python-for-Anweisung viel Arbeit, um die Schritte zu vereinfachen, sodass wir nicht manuell einen Iterator abrufen und next() aufrufen müssen, bis das Ende des Iterables erreicht ist.<\/P><\/P>Rückblick auf die SearchCursor -Dokumentation:<\/P>Zusammenfassung<\/P>SearchCursor stellt einen schreibgeschützten Zugriff auf die Datensätze bereit, die von einer Feature-Class oder Tabelle zurückgegeben werden.<\/P><\/P>Gibt einen Iterator von Tupeln zurück. Die Reihenfolge der Werte im Tupel entspricht der Reihenfolge der durch das Argument field_names angegebenen Felder.<\/P>Diskussion<\/P>Geometrie -Eigenschaften können durch Angabe des Tokens SHAPE@ in der Feldliste abgerufen werden.<\/P><\/P>Search Cursors können mit einer For-Schleife iteriert werden. [Entfernt ab Version 10.3.1: Search Cursors unterstützen auch With-Anweisungen; die Verwendung einer With-Anweisung garantiert das Schließen und Freigeben von Datenbanksperren und setzt die Iteration zurück].<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/BLOCKQUOTE><\/P>Wie man sieht, gibt die Dokumentation klar an, dass arcpy.da.SearchCursor einen Iterator zurückgibt, genauer gesagt einen Iterator von Tupeln. Es ist sinnvoll, Tupel statt Listen zurückzugeben, da wir einen SearchCursor verwenden, der keine Daten aktualisieren kann und Tupel per Design unveränderlich sind. Die zweite Aussage im Abschnitt Diskussion ist redundant, da for in Python über jedes Iterable iteriert, ob SearchCursor oder nicht, aber diese Aussage würde nicht als redundant auffallen, wenn Esri nicht den Rest des Absatzes entfernt hätte, der früher folgte.<\/P><\/P>Dies ist eine kleine Abschweifung zu einem Esri #fail, ein Beispiel dafür, wie man Kundenfeedback nicht behandeln sollte.<\/EM><\/P><\/P>Wie oben gezeigt wurde, enthielt Esri vor ArcGIS 10.3.1 einige Aussagen bezüglich Python with -Anweisungen. Die Tatsache, dass ArcPy Data Access Cursors with-Anweisungen unterstützen, ist erwähnenswert und könnte sogar dokumentiert werden. Das Problem mit den beiden Aussagen lag wirklich nur an der letzteren Aussage, ich garantiere es! Garantie ist ein starkes Wort, ein definitives Wort, und das Problem ist, dass nicht alle Datenbanksperren geschlossen und freigegeben werden.<\/EM><\/P><\/P>Ein Fehler wurde gemeldet zur Aktualisierung der Dokumentation, BUG-000083762: In jeder Cursor-Dokumentation soll angegeben werden, welche Art von Sperre geschlossen und freigegeben wird, da nach Ausführung der 'with'-Anweisung weiterhin eine Shared Lock in der Geodatabase vorhanden ist. Das Problem wurde in ArcGIS 10.3.1 als "behoben" markiert. Wenn Sie diese Klarstellung zu Sperren suchen möchten – ich habe sie Ihnen bereits gezeigt. Ja genau, es gibt keine Klarstellung mehr, sie haben einfach die Aussage über Sperren entfernt. Als ob das nicht genug wäre, haben sie auch eine sehr wichtige Aussage darüber entfernt, dass Data Access Cursors die Python-with-Anweisung unterstützen.<\/EM><\/P><\/P>Obwohl die Dokumentation über Iteratoren und Iteration spricht, wurde meiner Meinung nach eine echte Chance verpasst in den Codebeispielen eine praktische Python-Funktion zu demonstrieren. Viele ArcGIS-Nutzer, die neu in Python sind, lernen die Sprache durch Nachahmen von Codebeispielen. Was Pythonische Beispiele angeht sind die ArcPy Data Access Cursors eine gemischte Sache.<\/P>Codebeispiel<\/P>SearchCursor Beispiel 1
Verwenden Sie SearchCursor um eine Feature-Class zu durchlaufen und bestimmte Feldwerte sowie die x,y-Koordinaten des Punkts auszugeben.<\/P>
|
import arcpy<\/>\n<\/>\n<\/>\nfc = 'c:/data/base.gdb/well'
fields = ['WELL_ID', 'WELL_TYPE', 'SHAPE@XY'] <\/>
# Für jede Zeile WELL_ID und WELL_TYPE Felder sowie # x,y-Koordinaten des Features ausgeben
with arcpy.da.SearchCursor(fc, fields) as cursor:
for row in cursor:
print('{0}, {1}, {2}'.format(row[0], row[1], row[2])) <\\/p> <\\/td> <\\/tr> <\\/tbody> <\\/table> <\\/td> <\\/tr> <\\/tbody> <\\/table> <\\/blockquote>
Wie bereits in meiner vorherigen Anmerkung erwähnt wurde in der ArcPy Data Access Dokumentation nicht erwähnt, dass Cursors die Python-with-Anweisung unterstützen. Das heißt aber Unterstützung wird durch Verwendung von Python-with-Anweisungen in den Beispielen impliziert. Es lohnt sich also Zeit zu investieren um sich mit Python-with-Anweisungen vertraut zu machen, um deren Verwendung mit ArcPy Data Access Cursors wann immer möglich zu empfehlen. <\\/p>
Während die Dokumentationsbeispiele zeigen wie man Python-with-Anweisungen verwendet, wird trotz fehlender expliziter Erwähnung im Text selbst versäumt, die Verwendung von Iterable- oder Sequenzentpackung zu demonstrieren. Iterable oder Sequenz Entpacken ist eine großartige Funktion von Python und kann verwendet werden, um Code gleichzeitig viel kompakter und lesbarer zu machen. Das Sequenzentpacken wird kurz in der Python-Dokumentation für Tuples and Sequences erwähnt, und PEP 3132 -- Extended Iterable Unpacking bespricht Änderungen, die in Python 3.0 eingeführt wurden.<\/P>
<\/P> Schauen wir uns an, wie iterables Entpacken mit dem SearchCursor Beispiel 1 von oben verwendet werden kann.<\/P> import |