<\/HEAD>
Dit is het tweede deel in een serie met meerdere delen over ArcPy cursors; met name, werken met ArcPy cursors als iterabele objecten in Python. Het eerste deel in de serie<\/A> behandelt enkele van de belangrijke componenten van iteratie in Python. Het tweede deel in de serie<\/STRONG> behandelt het itereren en doorlopen van ArcPy Data Access cursors. Het derde deel in de serie <\/A>behandelt het gebruik van verschillende Python ingebouwde en itertools functies met ArcPy Data Access cursors. Het vierde deel in de serie zal het gebruik van generators of generatorexpressies behandelen om selectie- of filterlogica te scheiden voor hergebruik van code. Vijfde of volgende delen zijn op dit moment onbekend.<\/EM><\/P><\/P>
Het eerste deel in deze serie is waarschijnlijk wat academisch voor sommige ArcPy scripters, maar ik geloof dat een beetje theorie veel bijdraagt aan het begrijpen van de praktijk van iets, in dit geval het werken met ArcPy Data Access cursors op een idiomatische manier. Ook zullen de termen en concepten die in het eerste bericht worden uiteengezet steeds weer terugkomen gedurende de serie.<\/P>
<\/P>
Voordat we verder gaan, wil ik een aanbeveling doen voor een presentatie van een paar jaar geleden:
Loop Like A Native<\/A>. Ned Batchelder <\/A>geeft een mooie overzicht van looping in Python, vooral voor degenen met ervaring met loops in andere programmeertalen. Het heeft me meerdere keren kijken gekost voordat de hele presentatie tot me doordrong, maar het heeft echt mijn kijk op itereren en looping in Python veranderd.<\/P><\/P>
Herbruikend de Python lijst en ArcPy cursor voorbeelden uit het vorige bericht, laten we iter()<\/SPAN> aanroepen om een iterator terug te geven voor handmatig doorlopen van elke iterable.<\/P>>><\/SPAN>><\/SPAN> #maak lijst, koppel 2 iterators, en haal waarden op door<\/SPAN>
>><\/SPAN>><\/SPAN> # next() en object.next() aan te roepen<\/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>
<></span>
<></span>
<></span>
<></span>
<></span>
<></span>
<></span>
<></span>
<></span>
<></span>
<></span>
<></span>
<></span>
<p>Er valt nogal wat te zeggen over bovenstaande code:</p>
Eén enkele iterable kan meerdere iterators tegelijkertijd hebben die er toegang toe hebben. Hoe de iterable zich gedraagt met meerdere iterators is implementatiespecifiek.<ul>
Zoals de
iterator definitie stelt in de Python Verklarende Woordenlijst, een lijst "produceert elke keer dat je het doorgeeft aan een iter() functie of het gebruikt in een for-lus een verse nieuwe iterator." Dit verklaart waarom regels 06-07 en 08-09 dezelfde waarden afdrukken voor beide iterators.<\/LI>In tegenstelling tot de Python-lijst produceert de ArcPy Data Access zoekcursor geen nieuwe iterator, d.w.z. elke volgende oproep aan een iter() functie retourneert hetzelfde iteratorobject dat al in gebruik is. In dit soort situaties verplaatst elke oproep aan next() de iterator één element vooruit, ongeacht welke iterator de oproep doet. Dit verklaart waarom regels 16-17 de eerste en tweede OID tonen in plaats van de eerste OID twee keer.<\/LI><\/UL><\/LI>Een iterator kan worden verplaatst door gebruik te maken van de ingebouwde next() functie of de next-methode van het object. Vanaf Python 3.0, met de invoering van PEP 3114, is de voorkeur om handmatig te itereren de ingebouwde next() functie.<\/LI>Aangezien ArcPy Data Access cursors hun eigen iterator zijn, hoeft men geen iter() aan te roepen om een iteratorobject te krijgen voordat next() wordt aangeroepen. Regel 20 toont dat het cursorobject zelf kan worden doorgegeven aan next() om het volgende item op te halen en de cursor vooruit te bewegen.<\/LI><\/UL><\/P>Gelukkig doet de Python for-instructie veel werk om de stappen te vereenvoudigen zodat we niet handmatig een iterator hoeven op te halen en next() hoeven aan te roepen totdat het einde van het iterabele is bereikt.<\/P><\/P>Terugkomend op de SearchCursor documentatie:<\/P>Samenvatting<\/P>SearchCursor stelt alleen-lezen toegang in tot de records die worden geretourneerd uit een feature class of tabel.<\/P><\/P>Retourneert een iterator van tuples. De volgorde van waarden in de tuple komt overeen met de volgorde van velden gespecificeerd door het field_names argument.<\/P>Discussie<\/P>Geometry eigenschappen kunnen worden benaderd door het token SHAPE@ op te geven in de lijst met velden.<\/P><\/P>Zoekcursors kunnen worden geïtereerd met behulp van een For-lus. [Verwijderd bij 10.3.1: Zoekcursors ondersteunen ook With-instructies; het gebruik van een With-instructie garandeert sluiting en vrijgave van databaselocks en reset iteratie].<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/BLOCKQUOTE><\/P>Zoals men kan zien, stelt de documentatie duidelijk dat arcpy.da.SearchCursor een iterator retourneert, specifieker een iterator van tuples. Het is logisch dat het tuples retourneert in plaats van lijsten aangezien we een zoekcursor gebruiken die data niet kan bijwerken en tuples zijn per ontwerp onveranderlijk. De tweede uitspraak in de Discussiesectie is overbodig aangezien for in Python over elk iterabel object itereert, SearchCursor of anderszins, maar die uitspraak zou niet als overbodig opvallen als Esri niet de rest van de alinea had verwijderd die er vroeger op volgde.<\/P><\/P>Dit is een niet-zo-korte zijlijn over een Esri #fail, een voorbeeld van hoe je klantfeedback niet moet behandelen.<\/EM><\/P><\/P>Zoals hierboven getoond, bevatte Esri vóór ArcGIS 10.3.1 enkele uitspraken over Python with -instructies. Het feit dat ArcPy Data Access cursors with-instructies ondersteunen is het vermelden waard, zelfs documenteren zou je kunnen zeggen. Het probleem met die twee uitspraken was eigenlijk alleen het laatste statement, dat garandeer ik! Garantie is een sterk woord, een definitief woord, en het probleem is dat niet alle databaselocks worden gesloten en vrijgegeven.<\/EM><\/P><\/P>Er werd een bug ingediend om de documentatie bij te werken, BUG-000083762: In elke cursor-documentatie specificeren welk type lock wordt gesloten en vrijgegeven, aangezien er na uitvoering van de 'with'-instructie nog steeds een gedeelde lock aanwezig is in de geodatabase. Het probleem werd als "opgelost" gemarkeerd in ArcGIS 10.3.1. Als je die verduidelijking over locks wilt vinden, heb ik die al aan je getoond. Ja, die is er niet, ze hebben simpelweg het statement over locks verwijderd. Tot overmaat van ramp hebben ze ook een heel belangrijke uitspraak verwijderd over Data Access cursors die Python with-instructies ondersteunen.<\/EM><\/P><\/P>Hoewel de documentatie spreekt over iterators en itereren, vind ik dat er met de codevoorbeelden een echte kans gemist is om een handige Python-functie te demonstreren. Veel ArcGIS-gebruikers die nieuw zijn met Python leren de taal door codevoorbeelden na te bootsen. Wat betreft het tonen van Pythonische voorbeelden zijn de ArcPy Data Access cursors een gemengd geheel.<\/P>Codevoorbeeld<\/P>SearchCursor voorbeeld 1< /SPAN >< / P >< P > Gebruik SearchCursor om door een feature class te stappen en specifieke veldwaarden en de x,y-coördinaten van het punt af te drukken .< / P >< P >< / P >< TABLE stijl = "width :95 % ; border :1 px solid lightgrey ; background-color :#fafafa ; " >< TBODY >< TR >< TD >< P >< SPAN stijl = "font-family :courier new ,courier ; " >< SPAN stijl = "color :#0000ff ; " > import< / SPAN > arcpy< / SPAN >< / P >< P >< / P >< P >< SPAN stijl = "font-family :courier new ,courier ; " > fc = < SPAN stijl = "color :#a31515 ; " > 'c:/data/base.gdb/well' < / SPAN >< / SPAN >< BR />< SPAN stijl = "font-family :courier new ,courier ; " > fields = [< SPAN stijl = "color :#a31515 ; " > 'WELL_ID' < / SPAN > , < SPAN stijl = "color :#a31515 ; " > 'WELL_TYPE' < / SPAN > , < SPAN stijl = "color :#a31515 ; " > 'SHAPE@XY' < / SPAN > ]< / SPAN >< / P >< P >< / P >< P >< SPAN stijl = "color :#008000 ; font-family :courier new ,courier ; " > # Voor elke rij druk het WELL_ID en WELL_TYPE veld af , en de< / SPAN >< BR />< SPAN stijl = "color :#008000 ; font-family :courier new ,courier ; " > # x,y-coördinaten van het feature< / SPAN >< BR />< SPAN stijl = "font-family :courier new ,courier ; " >< SPAN stijl = "color :#0000ff ; " > with< / SPAN > arcpy.da.SearchCursor(fc , fields) < SPAN stijl = "color :#0000ff ; " > as< / SPAN > cursor:< / SPAN >< BR />< SPAN stijl = "font-family :courier new ,courier ; " > < SPAN stijl = "color :#0000ff ; " > for< / SPAN > row < SPAN stijl = "color :#0000ff ; " > in< / SPAN > cursor:< / SPAN >< BR />< SPAN stijl = "font-family :courier new ,courier ; " > < SPAN stijl = "color :#0000ff ; " > print< / SPAN >(<'{0}, {1}, {2}'>.format(row[0], row[1], row[2]))< / SPAN >< / P >< / TD >< / TR >< / TBODY >< / TABLE >< / TD >< / TR >< / TBODY >< / TABLE >< / BLOCKQUOTE >< P > Zoals aangegeven in mijn eerdere betoog/zijlijn vermeldt de ArcPy Data Access documentatie niet expliciet dat cursors Python < A href= "https://docs.python.org/2/reference/compound_stmts.html#the-with-statement" rel= "nofollow noopener noreferrer" target= "_blank" >< SPAN stijl= "font-family:courier new,courier" > with -instructies ondersteunen. . Dat gezegd hebbende wordt ondersteuning geïmpliceerd door het gebruik van Python Tuples and Sequences, en PEP 3132 -- Extended Iterable Unpacking bespreekt veranderingen geïntroduceerd in Python 3.0.<\/P><\/P>Laten we eens kijken hoe iterable unpacking kan worden gebruikt met SearchCursor voorbeeld 1 van hierboven.<\/P>import arcpy
fc = 'c:/data/base.gdb/well'
fields = ['WELL_ID', 'WELL_TYPE', 'SHAPE@XY'
]
# Voor elke rij print de WELL_ID en WELL_TYPE velden, en de
# de x,y coördinaten van het object
# Origineel voorbeeld met sequence indexing
with arcpy.da.SearchCursor(fc, fields) as cursor:
for row in cursor:
print('{0}, {1}, {2}'.format(row[0], row[1, row<SPAn class=