es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo detectar kwargs inválidos?

Estoy tratando de desarrollar un mecanismo para detectar kwargs inválidos que sea robusto para la herencia. Quiero crear una clase con un método init que verifique kwargs inesperados, y quiero crear otra clase que herede de esta primera clase con la misma verificación de kwargs. Esto podría ser más profundo que dos capas, pero creo que resolverlo para dos capas permitirá una extrapolación posterior. Aquí está mi intento:

class MyClass(object):
    def __init__(self, **kwargs):
        # posibles kwargs y valores predeterminados
        self._kwargs_def = {
            'a': 1,
            'b': 2,
            'c': 3,
        }
        self.a = kwargs.pop('a', self._kwargs_def['a'])
        self.b = kwargs.pop('b', self._kwargs_def['b'])
        self.c = kwargs.pop('c', self._kwargs_def['c'])

        assert len(kwargs) == 0, f"Invalid kwargs: {kwargs.keys()}"

class MyChildClass(MyClass):
    def __init__(self, **kwargs):
        super().__init__() # ejecutar una vez para generar _kwargs_def
        # repetir para anular los valores predeterminados con los kwargs apropiados
        super().__init__(**{key:val for key, val in kwargs.items() if key in super()._kwargs_def})

        self._kwargs_def.update({'d': 4, 'e': 5})

        self.d = kwargs.pop('d', self._kwargs_def['d'])
        self.e = kwargs.pop('e', self._kwargs_def['e'])

        assert len(kwargs) == 0, f"Invalid kwargs: {kwargs.keys()}"

my_instance = MyClass(a=7) # funciona
# Necesito una forma de solucionar esto: TypeError: descriptor '__init__' of 'super' object needs an argument
my_child_instance = MyChildClass(e=37) # no funciona pero debería???
my_instance = MyClass(z=7) # falla y debería fallar
my_child_instance = MyChildClass(z=37) # falla pero por la razón incorrecta
Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para solucionar los problemas en el código, las llamadas super().init() en la clase MyChildClass deben pasar **kwargs al constructor de la clase padre. Además, el método update() debe ser llamado en una copia de _kwargs_def en lugar del diccionario original. Aquí está el código actualizado:

    class MyClass:
        def __init__(self, **kwargs):
            self._kwargs_def = {'a': 1, 'b': 2, 'c': 3}
            self.a = kwargs.pop('a', self._kwargs_def['a'])
            self.b = kwargs.pop('b', self._kwargs_def['b'])
            self.c = kwargs.pop('c', self._kwargs_def['c'])
            assert not kwargs, f"Invalid kwargs: {kwargs.keys()}"
    
    class MyChildClass(MyClass):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            super().__init__(**{clave:valor for clave, valor in kwargs.items() if clave in self._kwargs_def})
            self._kwargs_def = self._kwargs_def.copy()
            self._kwargs_def.update({'d': 4, 'e': 5})
            self.d = kwargs.pop('d', self._kwargs_def['d'])
            self.e = kwargs.pop('e', self._kwargs_def['e'])
            assert not kwargs, f"Invalid kwargs: {kwargs.keys()}"
    

    Esto debería funcionar como se espera, permitiendo la detección de kwargs inválidos tanto en las clases padre como en las clases hijas, aunque ambas clases tienen sus propios kwargs predeterminados.

Comments are closed.