python reflection overriding subclass

python - Obtener funciones anuladas de subclase



reflection overriding (4)

¿Hay alguna manera de obtener todas las funciones anuladas de una subclase en Python?

Ejemplo:

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

Aquí, me gustaría obtener una lista ["a2"] para un objeto de la clase B (o para el objeto de la clase en sí) ya que la clase B anula un solo método, a saber, a2 .


Puede acceder a las clases primarias con cls.__bases__ , encontrar todos los atributos de los padres con dir y acceder a todos los atributos de la clase con 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''}


Puede hacer uso de la tupla __mro__ , que contiene el orden de resolución del método.

Por tu ejemplo:

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

Por lo tanto, puede recorrer esa tupla y verificar si un método B también está en una de las otras clases.


Solo para elaborar más, cuando define cualquier atributo se agrega al atributo __dict__ de la Class :

class A: def a1(self): pass print(''a1'' in A.__dict__) # True Note: vars(A) == A.__dict__

y para verificar si un atributo es un método, use built-in bruja callable built-in que devuelva un True si el objeto es callable (función, método, clase, ... etc.):

print(callable(A.__dict__[''a1''])) # True

Y ahora, incluso si B es una subclase de A pero no definió a1 ese atributo no se agrega a B.__dict__ :

class B(A): pass print(''a1'' in B.__dict__) # False

Entonces, simplemente comparando los valores de los atributos __dict__ obtendrás que el método de bruja se anula, que es el método que existe en A.__dict__ y B.__dict__

override_method = [attr for attr in B.__dict__ if attr in A.__dict__ and callable(A.__dict__[attr])]

Nota: Podría reemplazar A.__dict__ por vars(A) para simplificar el Código, pero quería mostrar este atributo especial que agrega Python para el nuevo desarrollador de Python.


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***