Keyクラスが2つある

Google App Engine PythonでデータストアのLow Level APIを触っていて、Keyクラスが2箇所で定義されていることに気が付きました。

from google.appengine.api.datastore import Key
from google.appengine.api.datastore_types import Key

datastoreモジュールとdatastore_typesモジュール。どっちからインポートしても同じように動作しました。クラスの別名みたいなものなのかな。

調べてみた

datastore_typesモジュールは、その名の通りデータストアに保存できる独自のデータ型を定義しているモジュールでした。「電話番号」型や「メールアドレス」型のようなクラスが並んでいます。
datastore_types.py
その中に「Key」クラスの定義もありました。データストアのデータ型としての「Key」クラスなので、おそらくReferencePropertyみたいな、他のエンティティを参照するデータ型に使われるんじゃないかなと思います。


datastoreモジュールの方にはKeyクラスの定義がありませんでした。「class Key」でgrepしても出てきません。しょうがないので「Key」で検索したら見つかりました。

Key = datastore_types.Key

datastore.py
なんだこりゃー!

びっくりした

pythonはリフレクションとかなしに「クラスへの参照」を変数に代入できるみたいです。クラスだけでなく関数やモジュールまでも、普通の代入で変数に入ります。関数が代入された変数は、そのまま()をつけるだけで実行することができました。
職業Javaプログラマにはちょっと刺激が強いです。。。

import datetime
mymodule = datetime
myclass = datetime.date
myfunction = datetime.date.today
myfunction() # datetime.date(2011, 4, 12)

本題に戻って

GAE/Pyでは「Key」クラスが以下の2モジュールで定義されている。

クラス定義はdatastore_typesモジュールの方で実装されていて、datastoreモジュールのKey変数がdatastore_types.Keyクラスを指している。実際はどちらも全く同じクラス。
モジュール名から予想するに、Keyクラスを他のエンティティのプロパティとして使用する場合はdatastore_typesモジュールからインポート。独立したエンティティがあって、それを識別するためのキーとして使用するならdatastoreモジュールからインポートするのがいいんじゃないかと思いました。