サブクラスのオーバーライドされた関数を取得する


19

Pythonでサブクラスのすべてのオーバーライドされた関数を取得する方法はありますか?

例:

class A:
    def a1(self):
        pass

    def a2(self):
        pass


class B(A):
    def a2(self):
        pass

    def b1(self):
        pass

ここで、私はリストを取得したい["a2"]クラスのオブジェクトのためにB(またはクラスオブジェクト自体の)クラスからBオーバーライドつだけの方法、すなわちa2

回答:


18

を使用して親クラスにアクセスし、を使用して親のcls.__bases__すべての属性を検索しdir、次を使用してクラス自体のすべての属性にアクセスできますvars

def get_overridden_methods(cls):
    # collect all attributes inherited from parent classes
    parent_attrs = set()
    for base in cls.__bases__:
        parent_attrs.update(dir(base))

    # find all methods implemented in the class itself
    methods = {name for name, thing in vars(cls).items() if callable(thing)}

    # return the intersection of both
    return parent_attrs.intersection(methods)
>>> get_overridden_methods(B)
{'a2'}

vars私が欠けていたものでした。(信じられないほど)速い答えに感謝します!
AndreasSchörgenhumer19年

parent_attrs必要に応じて1行に:parent_attrs = {a for b in cls.__bases__ for a in dir(b)}
wjandrea

3

__mro__メソッド解決の順序を保持するタプルを利用できます。

あなたの例のために:

>>> B.__mro__
( <class '__main__.B'>, <class '__main__.A'>, <class 'object'>) 

したがって、そのタプルをループして、Bメソッドが他のクラスの1つにもあるかどうかを確認できます。


これは、他のdunder メソッドのような定義済みメソッドを除外しません__init__, __eq__, ....... etc
Charif DZ

0
class A:

    def a1(self):
        pass

    def a2(self):
        pass


class B(A):

    def a2(self):
        super().a2()  
        pass

    def b1(self):
        pass
obj = B()

obj.a2()   # ***first give the output of parent class then child class***

1
あなたはその質問を誤解したと思います。クラスAB変更することはできません。OPは、BのメソッドのどれがAのメソッドの1つをオーバーライドするかを知りたいです。
wjandrea
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.