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.

Crear dos conjuntos de clases con diferentes herencias.

Tengo una clase base Foo y otra clase base Bar.

Me gustaría crear dos conjuntos de clases Baz (por ejemplo, Baz1, …, Baz20) de tal manera que para cada N del 1 al 20, haya una clase BazN que herede de Foo, y también una clase BazN que herede de Bar. Así que terminaría con 40 clases BazN, 20 de las cuales son BazNFoo y 20 de las cuales son del tipo BazNBar.

Lo que tengo es el siguiente fragmento de código, que escribe explícitamente cada clase BazN dos veces, una heredando de Foo y otra de Bar. Mi pregunta es, ¿hay alguna forma programática de hacer esto escribiendo cada clase BazN solo una vez? Mis clases Baz son bastante largas.

class Foo:
    def __init__(self):
        # código específico de Foo

class Bar:
    def __init__(self):
        # código específico de Bar

class Baz1Foo(Foo):
    def __init__(self):
        super().__init__()
        # código específico de Baz1

class Baz1Bar(Bar):
    def __init__(self):
        super().__init__()
        # código específico de Baz1

class Baz2Foo(Foo):
    ...
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Sí, puedes utilizar un enfoque programático para crear las clases Baz en lugar de escribir cada una explícitamente. Una forma de hacer esto es utilizando metaclasses.

    Aquí tienes un ejemplo de implementación:

    class MetaBaz(type):
        """
        Metaclass para crear las clases Baz.
        """
        def __new__(cls, name, bases, attrs):
            if name.startswith('Baz'):
                # obtener el número del nombre de la clase
                n = int(name[3:])
                # crear la clase que hereda de Foo
                attrs_foo = attrs.copy()
                attrs_foo.pop('__qualname__', None)  # para evitar conflictos con __qualname__
                bases_foo = (Foo,)
                name_foo = f'Baz{n}Foo'
                BazFoo = type(name_foo, bases_foo, attrs_foo)
                # crear la clase que hereda de Bar
                attrs_bar = attrs.copy()
                attrs_bar.pop('__qualname__', None)
                bases_bar = (Bar,)
                name_bar = f'Baz{n}Bar'
                BazBar = type(name_bar, bases_bar, attrs_bar)
                # retornar ambas clases
                return BazFoo, BazBar
            else:
                # para todas las demás clases, utilizar el comportamiento regular
                return super().__new__(cls, name, bases, attrs)
    
    
    class Foo:
        def __init__(self):
            # código específico para Foo
    
    class Bar:
        def __init__(self):
            # código específico para Bar
    
    class Baz1(metaclass=MetaBaz):
        def __init__(self):
            # código específico para Baz1
    
    ...
    
    class Baz20(metaclass=MetaBaz):
        def __init__(self):
            # código específico para Baz20
    

    En esta implementación, definimos una metaclass MetaBaz que es responsable de crear las clases Baz. Cuando se define una clase con un nombre que comienza por 'Baz', la metaclass crea dos subclases: una que hereda de Foo y otra que hereda de Bar. Luego retorna ambas subclases, creando efectivamente dos tipos de clases BazN con una sola definición de clase.

    Al definir las clases Baz, utilizamos la metaclass MetaBaz al establecer metaclass=MetaBaz en la definición de clase. Ya no es necesario crear explícitamente las clases BazNFoo y BazNBar, la metaclass se encarga de hacerlo por nosotros.

    Cabe mencionar que también eliminamos el atributo __qualname__ del diccionario attrs para evitar conflictos entre los nombres de las nuevas clases y el __qualname__ de la definición de clase original.

Comments are closed.