LoginSignup
15
14

More than 5 years have passed since last update.

python2 python3両方に対応できるmetaclassの書き方

Last updated at Posted at 2014-06-28

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
15
14
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
14