参考までに - getclasstree関数の動作

参考までに、inspectモジュールgetclasstree関数について調べた内容を記しておく。

以下のようなテストクラスを用意して

テストクラス

import inspect

class MyClsA(object):
    pass

class MyClsAS(MyClsA):
    pass

class MyClsASS(MyClsAS):
    pass

class MyClsASSS(MyClsASS):
    pass

class MyClsB(object):
    pass


class MyClsABS(MyClsA,MyClsB):
    pass

class MyClsAS2(MyClsA):
    pass

MyClsAのサブクラスであるMyClsASについてgetclasstree関数の戻り値を表示してみる。

例1-MyClsAS

classtree=inspect.getclasstree([MyClsAS])
print classtree

結果をみやすいようにインデントや改行を追加して整形してみると

実行結果

[
    (
        <class '__main__.MyClsA'>, 
        (
            <type 'object'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsAS'>, 
            (
                <class '__main__.MyClsA'>,
            )
        )
    ]
]

これだけではgetclasstree関数がどういうフォーマットの戻り値を返すのかわからない。
では、MyClsASのスーパクラスであるMyClsAはどうかというと

例2-MyClsA

classtree=inspect.getclasstree([MyClsA])
print classtree

実行結果

[
    (
        <type 'object'>, 
        ()
    ), 
    [
        (
            <class '__main__.MyClsA'>, 
            (
                <type 'object'>,)
        )
    ]
]

MyClsAのサブクラスであるMyClsASの更にサブクラスのそのまたサブクラスであるMyClsASSSについても調べてみる。

例3-MyClsASS

classtree=inspect.getclasstree([MyClsASSS])
print classtree

実行結果

[
    (
        <class '__main__.MyClsASS'>, 
        (
            <class '__main__.MyClsAS'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsASSS'>, 
            (
                <class '__main__.MyClsASS'>,
            )
        )
    ]
]

ここまで調べてきてなんとなくわかってきた。
どうやら、getclasstree関数は、第1要素にタプル,第2要素にリストの2つの要素を持つリストを返すようだ。

第1要素のタプル内の更に第1要素は、getclasstree関数の引数で指定したクラスのスーパクラスを指している。
すなわち、最初の例(例1)のgetclasstree関数の引数がMyClsASの場合にはMyClsASのスーパクラスであるMyClsAが,
例2のMyClsAの場合にはMyClsAのスーパクラスであるobjectが,
例3のMyClsASSSの場合にはMyClsASSSのスーパクラスであるMyClsASSが格納されている。
そして第1要素のタプル内の第2要素には、更にタプルが入れ子になっていて、第1要素の更にスーパクラスのタプルが格納されている。

第2要素のリストの内部にはこれもタプルが入れ子になっていて、そのタプルの第1要素は、関数の引数に指定されたクラスが、そして2番目の要素には第1要素のスーパクラスのタプルが格納されているようだ。

このように、getclasstree関数はクラスツリーをさかのぼって2つ前までのスーパクラスまでを探してきてくれるがそれ以上前までは探してくれないようだ。

では多重継承の場合はどうだろう。
MyClsAとMyClsBを多重継承したMyClsABSについてみてみよう。

classtree=inspect.getclasstree([MyClsABS])
print classtree

実行結果

[
    (
        <class '__main__.MyClsA'>, 
        (
            <type 'object'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsABS'>, 
            (
                <class '__main__.MyClsA'>, 
                <class '__main__.MyClsB'>
            )
        )
    ], 
    (
        <class '__main__.MyClsB'>, 
        (
            <type 'object'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsABS'>, 
            (
                <class '__main__.MyClsA'>, <class '__main__.MyClsB'>
            )
        )
    ]
]

多重継承の場合にはスーパクラスの数×2個の要素を持つリストを返す。
そして、それぞれのスーパクラスに対してタプルとリストの2個づつのペアになるようだ。

参考までに3つのクラスを多重継承した場合は、

class MyClsC(object):
    pass

class MyClsABCS(MyClsA,MyClsB,MyClsC):
    pass

classtree=inspect.getclasstree([MyClsABCS])

実行結果

[
    (
        <class '__main__.MyClsA'>, 
        (
            <type 'object'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsABCS'>, 
            (
                <class '__main__.MyClsA'>, 
                <class '__main__.MyClsB'>, 
                <class '__main__.MyClsC'>
            )
        )
    ], 
    (
        <class '__main__.MyClsB'>, 
        (
            <type 'object'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsABCS'>, 
            (
                <class '__main__.MyClsA'>, 
                <class '__main__.MyClsB'>, 
                <class '__main__.MyClsC'>
            )
        )
    ], 
    (
        <class '__main__.MyClsC'>, 
        (
            <type 'object'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsABCS'>, 
            (
                <class '__main__.MyClsA'>, 
                <class '__main__.MyClsB'>, 
                <class '__main__.MyClsC'>
            )
        )
    ]
]

これまでは、1つのクラスだけを引数に指定したが、複数のクラスを指定してやると

classtree=inspect.getclasstree([MyClsASS,MyClsABS])
print classtree

実行結果

[
    (
        <class '__main__.MyClsA'>, 
        (
            <type 'object'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsABS'>, 
            (
                <class '__main__.MyClsA'>, 
                <class '__main__.MyClsB'>
            )
        )
    ], 
    (
        <class '__main__.MyClsAS'>, 
        (
            <class '__main__.MyClsA'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsASS'>, 
            (
                <class '__main__.MyClsAS'>,
            )
        )
    ], 
    (
        <class '__main__.MyClsB'>, 
        (
            <type 'object'>,
        )
    ), 
    [
        (
            <class '__main__.MyClsABS'>, 
            (
                <class '__main__.MyClsA'>, 
                <class '__main__.MyClsB'>
            )
        )
    ]
]

MyClsASSとMyClsABSの個々のスーパクラスMyClsASとMyClsAとにMyClsBに対するそれぞれのタプルとリストを要素に持つ、更に複雑怪奇なリストが返される事になる。

ここまで時間をかけてgetclasstree関数の出力をみてきたのだが、果たしてこれが何の役に立つのかというとさっぱりわからない。
苦労して調べた割には得るものがまったく無かった。

ページのトップへ戻る