2014/08/19

Python Tips:クラスの継承関係をチェックしたい

Pythonで「クラス間の継承関係をチェックする方法」をご紹介します。

クラスの継承関係をチェックするために使える関数として、次の2つの関数があります。
issubclass
mro

以下、順番に見ていきます。まずは issubclass から。


issubclass
issubclass は引数を2つ取る関数で、ひとつめにサブクラスを、ふたつめにスーパークラスを受け取ります。

ひとつめの引数に渡したクラスがふたつめに渡したクラスのサブクラスであれば True 、そうでなければ False を返してくれます。

たとえばこんな感じ。
# スーパークラス Dog
class Dog(object):
    pass

# サブクラス BigDog
# Dog を継承しているので継承関係は BigDog < Dog < object
class BigDog(Dog):
    pass

print issubclass(BigDog, Dog)  # => True
print issubclass(BigDog, object)  # => True

BigDog と object のように、ふたつのクラスが直接の親子関係にない場合も、祖先/子孫のどこかにあれば True を返してくれます。


mro
mro は引数にクラスを受け取る関数です。受け取ったクラスの祖先クラスを「名前解決を行う順番に並べた上で」リストに格納して返してくれます。

Rubyでいうなら ancestors メソッドでしょうか。

ちなみに mro というのは Method Resolution Order (メソッド名前解決順序)の略だそうです。そのまんま!

実際の使い方はたとえばこんな感じです。
# スーパークラス その1
class Pug(object):
    pass

# スーパークラス その2
class ShihTzu(object):
    pass

# パグとシーズーを両親に生まれたサブクラス
# パズー
class PugZu(Pug, ShihTzu):
    pass

# PugZu に対して mro() を呼び出す
print PugZu.mro()
# => [__main__.PugZu, __main__.Pug, __main__.ShihTzu, object]
# メソッドの名前解決を行う順番で基底の object までさかのぼって表示する

PugZu をレシーバに mro を呼び出すと、 PugZu の祖先となるクラスがすべて表示されます。

まわりくどいやり方ですが、この mro 関数と in を使えば issubclass と同じ結果を得ることなども可能です。
print ShihTzu in PugZu.mro()
# => True
# issubclass でチェックしたのと同じ結果が現れる


以上です。


参考
python - Test if a class is inherited from another - Stack Overflow
The Python 2.3 Method Resolution Order - Python公式ドキュメント



0 件のコメント: