Herencia de metaclases en Python
Tengo una metaclase simple que convierte los métodos de las clases que comienzan con “get_” en propiedades:
class PropertyConvertMetaclass(type):
def __new__(mcs, future_class_name, future_class_parents, future_class_attr):
new_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'):
if name.startswith('get_'):
new_attr[name[4:]] = property(val)
else:
new_attr[name] = val
return type.__new__(mcs, future_class_name, future_class_parents, new_attr)
Imaginemos que tengo la clase TestClass:
class TestClass():
def init(self, x: int):
self._x = x
def get_x(self):
print("this is property")
return self._x
Quiero que funcione de la siguiente manera: Creo una nueva clase que hereda de ambas clases:
class NewTestClass(TestClass, PropertyConvertMetaclass):
pass
Y quiero poder reutilizar los métodos de ambas clases de la siguiente manera:
obj = NewTestClass(8)
obj.get_x() # 8
obj.x # 8
Según entiendo, debería crear una nueva clase llamada PropertyConvert y hacer que NewTestClass herede de ella:
class PropertyConvert(metaclass=PropertyConvertMetaclass):
pass
class NewTestClass(TestClass, PropertyConvert):
pass
Pero esto no ayuda, todavía no puedo usar el nuevo método de propiedad con NewTestClass. ¿Cómo puedo hacer que PropertyConvert herede todos los métodos de su hermano, sin hacer nada dentro de NewTestClass, cambiando solo PropertyConverterMetaclass o PropertyConverter? Soy nuevo en las metaclasses, así que disculpa si esta pregunta parece tonta.
davy.ai
El problema con la implementación actual es que la metaclase
PropertyConvertMetaclass
solo convierte los métodos con el prefijoget_
en propiedades al crearNewTestClass
. CuandoPropertyConvert
se define como una clase separada conPropertyConvertMetaclass
como su metaclase, no tiene ningún método para convertir a propiedades, por lo que la metaclase no se invoca en él.Para asegurarnos de que
PropertyConvert
herede todas las propiedades convertidas deNewTestClass
, podemos modificar la metaclase para convertir los métodos en propiedades cuando se creaPropertyConvert
también.Una forma de lograr esto es agregar una comprobación en el método
__new__
dePropertyConvertMetaclass
para ver si la clase que se está creando esPropertyConvert
. Si lo es, simplemente podemos devolver la clase sin hacer ningún cambio. De lo contrario, podemos seguir adelante y convertir los métodos en propiedades como antes.Aquí está la metaclase modificada:
Ahora, cuando definamos
PropertyConvert
conPropertyConvertMetaclass
como su metaclase, heredará todas las propiedades deNewTestClass
:Ten en cuenta que no necesitamos hacer ningún cambio en
NewTestClass
en sí. Toda la magia ocurre a nivel de la metaclase.