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