<\/HEAD>
これはArcPyカーソルに関する複数回シリーズの第2回目です。特に、Pythonで反復可能なオブジェクトとしてArcPyカーソルを扱うことについてです。 シリーズの第1回目<\/A>では、Pythonの反復処理における重要な要素のいくつかを見ています。 シリーズの第2回目<\/STRONG>では、ArcPy Data Accessカーソルの反復とループ処理について説明します。 シリーズの第3回目<\/A>では、ArcPy Data AccessカーソルでいくつかのPython組み込み関数やitertools関数を使う方法を見ます。 シリーズの第4回目では、コードの再利用のために選択やフィルタリングロジックを分離するジェネレーターやジェネレーター式の使用について説明します。第5回以降は現時点では未定です。<\/EM><\/P><\/P>
このシリーズの第1回目は、一部のArcPyスクリプターには少し学術的すぎるかもしれませんが、理論を少し理解することは、実践、つまりここではArcPy Data Accessカーソルを慣用的に扱うことを理解する上で非常に役立つと私は考えています。 また、第1回目で示した用語や概念はシリーズ全体で何度も登場します。<\/P>
<\/P>
先に進む前に、数年前のプレゼンテーションを紹介します:
Loop Like A Native<\/A>. Ned Batchelder<\/A>は、特に他のプログラミング言語でループ経験がある人向けに、Pythonでのループ処理についてわかりやすく解説しています。私はこのプレゼンテーションを何度も見てようやく理解できましたが、本当にPythonでの反復とループ処理を見る視点が変わりました。<\/P><\/P>
前回の記事からPythonリストとArcPyカーソルの例を再利用して、iter()<\/SPAN>を呼び出して各反復可能オブジェクトを手動でステップ処理するイテレーターを返しましょう。<\/P>>><\/SPAN>><\/SPAN> #リストを作成し、2つのイテレーターを割り当てて値を取得するために<\/SPAN>
>><\/SPAN>><\/SPAN> # next() と object.next() を呼び出す<\/SPAN>
>><\/SPAN>><\/SPAN> l =<\/SPAN> [10, 20, 30, 40, 50]
>><\/span>><\/span> it_l =<\/span> iter(l)<\/span>
>><\/span>><\/span> it2_l =<\/span> iter(l)<\/span>
>><\/span>><\/span> print<\/span> next(it_l)<\/span>, next(it2_l)<\/span>
10<\/span> 10<\/span>
>><\/span>><\/span> print<\/span> it_l.<\/span>next()<\/span>, it2_l.<\/span>next()<\/span>
20<\/span> 20<\/span>
>><\/span>><\/span>
>><\/span>><\/span> #検索カーソルを作成し、2つのイテレーターを割り当てて値を取得するために<\/span>
>><\/span>><\/span> # next と object.next() を呼び出す<\/span>
>><\/span>><\/span> cur =<\/span> arcpy.<\/span>da.<\/span>SearchCursor(fc, ["OID@", "SHAPE@"<\/>\n<続き> rel="nofollow noopener noreferrer" target="_blank">Python用語集
、リストは「iter()関数に渡すたび、またはforループで使用するたびに新しいイテレータを生成します。」 これが、06-07行目と08-09行目で両方のイテレータが同じ値を出力している理由の説明です。<\/LI>Pythonのリストとは対照的に、ArcPy Data Accessのsearch cursorは新しいイテレータを生成しません。つまり、iter()関数を呼び出すたびに、既に使用中の同じイテレータオブジェクトが返されます。 このような状況では、どのイテレータが呼び出しても、next()の呼び出しごとにイテレータは1つ先の要素に進みます。 これが16-17行目で最初と2番目のOIDが表示され、最初のOIDが2回表示されない理由です。<\/LI><\/UL><\/LI>イテレータは組み込みのnext()関数かオブジェクトのnextメソッドを使って進めることができます。 Python 3.0以降では、PEP 3114の採用により、手動で反復処理を行う推奨方法は組み込みのnext()関数です。<\/LI>ArcPy Data Accessのカーソルはそれ自体がイテレータなので、next()を呼び出す前にイテレータオブジェクトを取得するためにiter()を呼ぶ必要はありません。 20行目ではカーソルオブジェクト自体をnext()に渡して次のアイテムを取得しカーソルを進めています。<\/LI><\/UL><\/P>幸いなことに、Pythonのfor文は多くの処理を自動化しており、手動でイテレータを取得したり、反復可能オブジェクトの終わりまでnext()を呼び出したりする必要がありません。<\/P><\/P>SearchCursor ドキュメントを再確認します:<\/P>概要<\/P>SearchCursorはフィーチャクラスまたはテーブルから返されたレコードへの読み取り専用アクセスを確立します。<\/P><\/P>タプルのイテレータを返します。タプル内の値の順序は、field_names 引数で指定されたフィールドの順序と一致します。<\/P>解説<\/P>Geometry プロパティにはフィールドリストにトークンSHAPE@を指定してアクセスできます。<\/P><\/P>SearchCursorはForループで反復処理できます。[10.3.1で削除: SearchCursorはWith文もサポートしています;With文を使うことでデータベースロックのクローズと解放、および反復状態のリセットが保証されます]。<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/BLOCKQUOTE><\/P>ご覧の通り、ドキュメントには明確にarcpy.da.SearchCursorがイテレータ(具体的にはタプルのイテレータ)を返すと記載されています。更新できない検索カーソルなのでリストではなく不変なタプルを返すことは理にかなっています。解説セクション内の2番目の文は冗長ですが、Pythonのfor文はSearchCursorに限らず任意の反復可能オブジェクト上で反復処理するため、その文自体は冗長でもEsriが後続段落全体を削除しなければ気づかれなかったでしょう。<\/P><\/P>これはEsriによる失敗例として顧客フィードバック対応のお手本にならない話です。<\/P><\/P>上記で示したように、ArcGIS 10.3.1以前ではEsriはPython with文についていくつか記述していました。ArcPy Data Accessカーソルがwith文をサポートしている事実は指摘する価値がありますし、ドキュメント化すべきとも言えます。この2つの記述問題は後者にあり、それが問題だと私は断言します!断言とは強い言葉であり決定的な言葉ですが、問題はすべてのデータベースロックがクローズ・解放されているわけではない点です。<\/P><\/P>ドキュメント更新用バグ報告が提出されました:BUG-000083762:各カーソルドキュメントで閉じられ解放されるロック種別を明示してください。'with'文実行後もジオデータベースには共有ロックが残っています。 この問題はArcGIS 10.3.1で「修正済み」とされています。そのロックについての説明をご自身で探したいなら既にお見せしましたよ。そうです、それは存在せず単純にロックについての記述だけ削除されました。そしてさらに悪いことにData AccessカーソルがPython with文をサポートしているという非常に重要な記述も削除されました。<\/P><\/P>ドキュメントではイテレータや反復処理について触れていますが、コード例で便利なPython機能を示す絶好の機会が失われたと感じます。多くのArcGISユーザーはPython初心者としてコード例を模倣して学習します。Python的な例示という観点ではArcPy Data Accessカーソルは賛否両論です。
コード例 SearchCursor例1 SearchCursorを使ってフィーチャクラスを順番に処理し特定フィールド値とポイントのx,y座標を印刷します。 import arcpy fc = 'c:/data/base.gdb/well' fields = ['WELL_ID', 'WELL_TYPE', 'SHAPE@XY'] # 各行についてWELL_IDとWELL_TYPEフィールド、および# フィーチャーのx,y座標を印刷するwith arcpy.da.SearchCursor(fc, fields) as cursor: for row in cursor: print('{0}, {1}, {2}'.format(row[0], row[1], row[2])) |
|
前述した私見/余談でも指摘したように、ArcPy Data AccessドキュメントにはカーソルがPython with 文 をサポートしているとは明記されていません。しかしながら例示コード中でPython with
文 が使われていることからサポートされていることは暗黙的に示されています。Python
with 文 を学ぶ価値は十分あり、可能な限りArcPy Data Accessカーソルでも使用することを推奨します。
< /p >
ドキュメント例ではPython with
文 の使用法は示していますが、反復可能オブジェクトやシーケンスアンパッキングの使用例までは示せていません。反復可能またはシーケンス アンパッキングはPythonの素晴らしい機能であり、コードをよりコンパクトで読みやすくするために同時に使用できます。 シーケンスのアンパッキングはPythonドキュメントの
Tuples and Sequencesで簡単に言及されており、
PEP 3132 -- Extended Iterable Unpacking ではPython 3.0で導入された変更について説明されています。<\/P>
<\/P>
上記のSearchCursorの例1を使って、イテラブルアンパッキングがどのように使えるか見てみましょう。<\/P>
import