python2.xとpython3.xでmetaclassを利用する構文が異なっている。
一方でひとつのファイルで両方のバージョンをサポートしたいことがある。
そのような場合の書き方について。
metaclass(HasVersion)
以下のようなmetaclass HasVersionMetaがある。
単にversion番号のような文字列を持っているというだけのmetaclass。
class HasVersionMeta(type):
def __new__(cls, name, bases, attrs):
attrs["version"] = "0.0.1"
return super(HasVersionMeta, cls).__new__(cls, name, bases, attrs)
これを使ったclassを定義したい。
python3の場合
python3の場合は継承の際に渡す引数の箇所にmetaclassオプションを付ける。
class A(object, metaclass=HasVersionMeta):
pass
python2の場合
python2の場合は、__metaclass__という特別な名前のhookに代入する
class A(object):
__metaclass__ = HasVersionMeta
両方に対応する場合
metaclassとして使われるクラスはcallable objectでもあり。
親classになるtype()が動的にclassを生成される際に使われることを考えると同じ機能をもっているはず。
なので以下のように書けば良い。
HasVersion = HasVersionMeta("A", (object, ), {"__doc__": HasVersionMeta.__doc__})
class A(HasVersion):
pass
動作する。
print(A.version)
# 0.0.1