<\/HEAD>
Toto je druhý díl vícedílné série o ArcPy kurzorech; konkrétně o práci s ArcPy kurzory jako iterovatelnými objekty v Pythonu. První díl série<\/A> se zabývá některými důležitými komponentami iterace v Pythonu. Druhý díl série<\/STRONG> se zaměřuje na iterování a cyklení přes ArcPy Data Access kurzory. Třetí díl série <\/A>se věnuje použití několika vestavěných funkcí Pythonu a itertool funkcí s ArcPy Data Access kurzory. Čtvrtý díl série se bude zabývat použitím generátorů nebo generátorových výrazů k oddělení logiky výběru nebo filtrování pro opětovné použití kódu. Páté nebo následující díly jsou zatím neznámé.<\/EM><\/P><\/P>
První díl této série může být pro některé ArcPy skriptéry poněkud akademický, ale věřím, že trochu teorie velmi pomáhá pochopit praxi něčeho, v tomto případě práci s ArcPy Data Access kurzory idiomatickým způsobem. Také termíny a koncepty uvedené v prvním příspěvku se budou v celé sérii opakovaně objevovat.<\/P>
<\/P>
Než budeme pokračovat, rád bych doporučil prezentaci z před několika lety:
Loop Like A Native<\/A>. Ned Batchelder <\/A>představuje pěkný přehled o cyklení v Pythonu, zejména pro ty, kteří mají zkušenosti s cyklením v jiných programovacích jazycích. Trvalo mi několik shlédnutí, než jsem celou prezentaci plně pochopil, ale opravdu to změnilo můj pohled na iterování a cyklení v Pythonu.<\/P><\/P>
Recyklujeme příklady Python seznamu a ArcPy kurzoru z předchozího příspěvku, zavoláme iter()<\/SPAN>, abychom získali iterátor pro ruční krokování přes každý iterovatelný objekt.<\/P><SPAN class="operator token">>><\/SPAN><SPAN class="operator token">><\/SPAN> <SPAN class="comment token">#vytvořit seznam, připojit 2 iterátory a získat hodnoty voláním<\/SPAN>
<SPAN class="operator token">>><\/SPAN><SPAN class="operator token">><\/SPAN> <SPAN class="comment token"># next() a object.next()<\/SPAN>
<SPAN class="operator token">>><\/SPAN><SPAN class="operator token">><\/SPAN> l <SPAN class="operator token">=<\/SPAN> <SPAN class="punctuation token">[<\/SPAN><SPAN class="number token">10<\/SPAN><SPAN class="punctuation token">,<\/SPAN> <SPAN class="number token">20<\/SPAN><SPAN class="punctuation token">,<\/SPAN> <SPAN class="number token">30<\/SPAN><SPAN class="punctuation token">,<\/SPAN> <SPAN class="number token">40<\/SPAN><SPAN class="punctuation token">,<\/SPAN> <SPAN class="number token">50<\/SPAN><SPAN class="punctuation token">]<\/SPAN>
<SPAN class="operator token">>><\/SPAN><SPAN class="operator token">><\/SPAN> it_l <SPAN class="operator token">=<\/SPAN> iter<SPAN class="punctuation token">(<\/SPAN>l<SPAN class="punctuation token">)<\/SPAN>
<SPAN class="operator token">>><\/SPAN><SPAN class="operator token">><\/SPAN> it2_l <SPAN class="operator token">=<\/SPAN> iter<SPAN class="punctuation token">(<\/Span>l<Span class=\"punctuation token\">)<\span>
<span class=\"operator token\">>><\span><span class=\"operator token\">><\span> print next(it_l), next(it2_l)
10 10
>>> print it_l.next(), it2_l.next()
20 20
>>>
>>> #vytvořit search cursor, připojit 2 iterátory a získat hodnoty voláním
>>> # next a 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, <Polyline object at 0x1100fcf0[0x1100ff20]>) (2, <Polyline object at 0x1100fcf0[0x1100ff20]>)
>>> print it_cur.next(), it2_cur.next()
(3, <Polyline object at 0x1100fcf0[0x1100ff20]>) (4, <Polyline object at 0x1100fcf0[0x1100ff20]>)
>>> print next(cur)
(5, <Polyline object at 0x1100fcf0[0x1100ff20]>)
>>>
<span class=\"line-numbers-rows\"><span><<EMOJI_0></span><span><<EMOJI_1></span><span><<EMOJI_2></span><span><<EMOJI_3></span><span><<EMOJI_4></span><span><<EMOJI_5></span><span><<EMOJI_6></span><span><<EMOJI_7></span><span><<EMOJI_8></span><span><<EMOJI_9></span><span><<EMOJI_10></span><span><<EMOJI_11></span><span><<EMOJI_12></span><span><<EMOJI_13></span><span><<EMOJI_14></span><span><<EMOJI_15></span><span><<EMOJI_16></span><span><<EMOJI_17></span><span><<EMOJI_18></span><span><<EMOJI_19></span><span><<EMOJI_20></span><span><<EMOJI_21></span></span>
Kód výše nabízí poměrně hodně k komentování:
- Jeden iterovatelný objekt může mít současně více iterátorů přistupujících k němu. Jak se iterovatelný objekt chová při více iterátorech závisí na implementaci.
iterátoru<\/_A> ve slovníku pojmů Pythonu rel="nofollow noopener noreferrer" target="_blank">Python Slovník pojmů, seznam "vytváří pokaždé nový iterator, když jej předáte funkci iter() nebo použijete v cyklu for." To vysvětluje, proč řádky 06-07 a 08-09 tisknou stejné hodnoty pro oba iterátory.<\/LI>Na rozdíl od Python seznamu ArcPy Data Access search cursor nevytváří nový iterator, tj. každý následující volání funkce iter() vrací stejný objekt iteratoru, který je již používán. V těchto situacích každé volání next() posune iterator o jeden prvek vpřed bez ohledu na to, který iterator volání provádí. To vysvětluje, proč řádky 16-17 ukazují první a druhý OID místo zobrazení prvního OID dvakrát.<\/LI><\/UL><\/LI>Iterator lze posunout vpřed použitím buď vestavěné funkce next() nebo metody next objektu. Od Python 3.0, s přijetím PEP 3114, je preferovanou metodou manuální iterace vestavěná funkce next().<\/LI>Jelikož ArcPy Data Access cursory jsou samy o sobě iterátory, není potřeba volat iter() pro získání objektu iteratoru před voláním next(). Řádek 20 ukazuje, že samotný kurzor může být předán do next() pro získání další položky a posunutí kurzoru vpřed.<\/LI><\/UL><\/P>Naštěstí za nás příkaz Python for dělá hodně práce, aby zjednodušil kroky tak, že nemusíme ručně získávat iterator a volat next(), dokud nedojdeme na konec iterovatelného objektu.<\/P><\/P>Znovu k dokumentaci SearchCursor :<\/P>Shrnutí<\/P>SearchCursor zajišťuje přístup pouze pro čtení k záznamům vráceným z feature class nebo tabulky.<\/P><\/P>Vrací iterator n-tic. Pořadí hodnot v n-tici odpovídá pořadí polí specifikovaných argumentem field_names .<\/P>Diskuse<\/P>Vlastnosti Geometry lze přistupovat zadáním tokenu SHAPE@ do seznamu polí.<\/P><\/P>Search cursory lze iterovat pomocí cyklu For. [Odstraněno ve verzi 10.3.1: Search cursory také podporují With příkazy; použití With příkazu zajistí uzavření a uvolnění databázových zámků a resetování iterace].<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/BLOCKQUOTE><\/P>Jak je vidět, dokumentace jasně uvádí, že arcpy.da.SearchCursor vrací iterator, konkrétně iterator n-tic. Dává smysl vracet n-tice místo seznamů, protože používáme search cursor, který nemůže data aktualizovat a n-tice jsou podle návrhu neměnné. Druhé tvrzení v sekci Diskuse je nadbytečné, protože for v Pythonu iteruje přes jakýkoli iterable objekt, SearchCursor nebo jinak, ale toto tvrzení by nevypadalo jako nadbytečné, kdyby Esri neodstranilo zbytek odstavce, který následoval.<\/P><\/P>Toto je ne tak rychlá vsuvka o Esri #failu, příklad toho, jak nezpracovat zpětnou vazbu zákazníků správně.<\/EM><\/P><\/P>Jak je uvedeno výše, před verzí ArcGIS 10.3.1 Esri zahrnovalo několik tvrzení týkajících se Python with příkazů. Skutečnost, že ArcPy Data Access cursory podporují with příkazy stojí za zmínku, dokonce by se dalo říct i za dokumentaci. Problém s těmito dvěma tvrzeními byl opravdu jen problém s tím druhým tvrzením, to garantuji! Garantovat je silné slovo, definitivní slovo a problém je v tom, že ne všechny databázové zámky jsou uzavřeny a uvolněny.<\/EM><\/P><\/P>Byl podán bug report pro aktualizaci dokumentace, BUG-000083762: V dokumentaci ke každému kurzoru specifikovat typ zámku, který je uzavřen a uvolněn, protože sdílený zámek stále přetrvává v geodatabázi po vykonání 'with' příkazu. Problém byl označen jako "vyřešený" v ArcGIS 10.3.1. Pokud chcete najít toto upřesnění ohledně zámků, už jsem vám ho ukázal. Ano, žádné tam nejsou, prostě odstranili tvrzení o zámcích. Jako třešnička na dortu odstranili také velmi důležité tvrzení o podpoře Python with příkazu u Data Access kurzorů.<\/EM><\/P><\/P>Ačkoliv dokumentace hovoří o iterátorech a iterování, mám pocit, že byla promarněna skutečná příležitost v ukázkových kódech demonstrovat užitečnou vlastnost Pythonu. Mnoho uživatelů ArcGIS nových v Pythonu se učí jazyk napodobováním ukázkových kódů. Co se týče ukázky pythonických příkladů, ArcPy Data Access cursory jsou smíšenou sadou.<\/P>Ukázka kódu<\/P>SearchCursor příklad 1
Použijte SearchCursor k průchodu feature class a vytiskněte specifické hodnoty polí a souřadnice x,y bodu.<\/P>
|
import arcpy<\/>
fc = 'c:/data/base.gdb/well'
fields = ['WELL_ID', 'WELL_TYPE', 'SHAPE@XY']<\/>
# Pro každý řádek vytiskněte pole WELL_ID a WELL_TYPE a
# souřadnice x,y prvku
with arcpy.da.SearchCursor(fc, fields) as cursor:
for row in cursor:
print('{}{}, {}{}'.format(row[0], row[1], row[2]))
|
A jak jsem zmínil ve své dřívější vsuvce/soapboxu, dokumentace ArcPy Data Access neuvádí podporu Python with-příkazů u kurzorů.& nbsp ;Podpora je však naznačena použitím Python with-příkazů v příkladech.& nbsp ;Stojí za to si přečíst o Python with-příkazech a doporučuji jejich použití s ArcPy Data Access kurzory kdykoli je to možné.
Zatímco příklady v dokumentaci demonstrují použití Python with-příkazů i když dokumentace sama neuvádí jejich podporu , příklady selhávají v demonstraci použití rozbalování iterable nebo sekvence . Iterable nebo sekvence rozbalování je skvělá vlastnost Pythonu a může být použita k tomu, aby byl kód mnohem kompaktnější a zároveň čitelnější. Rozbalování sekvencí je stručně zmíněno v dokumentaci Pythonu pro Tuples and Sequences, a PEP 3132 -- Extended Iterable Unpacking diskutuje změny zavedené v Pythonu 3.0.<\/P>
<\/P>
Pojďme se podívat, jak lze použít rozbalování iterovatelných objektů na příkladu SearchCursor příklad 1 výše.<\/P>
import