2009-01-24 16 views
14

Recientemente descubrí metaclases en python.¿Alguien usa meta-meta-classes/meta-meta-meta-classes en Python/otros lenguajes?

Básicamente una metaclase en python es una clase que crea una clase. Hay muchas razones útiles por las que desearía hacer esto: cualquier clase de inicialización de clase, por ejemplo. Registrar clases en fábricas, validación compleja de atributos, alterar cómo funciona la herencia, etc. Todo esto no solo es posible sino también simple.

Pero en python, las metaclases también son clases simples. Así, empecé a preguntarme si la abstracción sería útil ir más alto, y me parece que se puede y que:

  • una metaclase corresponde ao implementa un papel en un patrón (como en los lenguajes de patrones GOF).
  • un meta-metaclase es el patrón en sí (si permitimos que para crear tuplas de clases que representan papeles abstractos, en lugar de una sola clase)
  • un meta-meta-metaclase es una fábrica patrón, que corresponde a las agrupaciones de patrones GOF, por ejemplo Creational, Structural, Behavioral. Una fábrica donde podría describir un caso de cierto tipo de problema y le daría un conjunto de clases que lo resolvió.
  • meta-meta-metaclass (hasta donde pude), es una fábrica fábrica de patrones, una fábrica en la que quizás podría describir el tipo de su problema y le daría una fábrica de patrones para pedir.

He encontrado algunas cosas sobre esto en línea, pero sobre todo no muy útiles. Un problema es que diferentes idiomas definen las metaclases de forma ligeramente diferente.

¿Alguien más ha usado metaclasses como este en python/en otro lugar, o visto esto usado en la naturaleza, o pensado en eso? ¿Cuáles son los análogos en otros idiomas? P.ej. en C++, ¿a qué profundidad puede llegar la recursión de la plantilla?

Me gustaría investigar más.

+0

Actualización: ha pasado mucho tiempo. Usé mucho las metaclases y creo que fueron útiles, pero luego me salí completamente de las metaclases. La razón es que después de examinar la interacción del contexto del dominio y algunas investigaciones de IBM, me di cuenta de que el concepto de que el tipo es intrínseco a un objeto es en sí mismo defectuoso. En cambio, el tipo depende de "a quién preguntar". Para un pájaro, un árbol es solo un lugar para construir un nido. Para un maderero, una fuente de ingresos, para un tasador de impuestos, tal vez otra cosa. –

Respuesta

4

El sistema de clases en Smalltalk es interesante de estudiar. En Smalltalk, todo es un objeto y cada objeto tiene una clase. Esto no implica que la jerarquía vaya al infinito. Si no recuerdo mal, es algo como:

5 -> Entero -> clase Entero -> MetaClass -> clase MetaClass -> MetaClass -> ... (se realiza un bucle)

Donde '->' denota "es una instancia de".

+0

Gracias, algunas otras personas mencionaron smalltalk. Tendré que desenterrarme squeak VM y comparar las metaclases de Smalltalk con las de Python. –

7

Para responder a su pregunta: no.

No dude en investigar más.

Nótese, sin embargo, que ha fusionado patrones de diseño (que son sólo ideas) con el código (que es una implementación.)

Buena código menudo refleja una serie de patrones de diseño de enclavamiento. No hay una manera fácil de formalizar esto. Lo mejor que puede hacer es una buena imagen, docstrings bien escritos y nombres de métodos que reflejen los diversos patrones de diseño.

También tenga en cuenta que una metaclase es una clase. Eso es un bucle. No hay un nivel más alto de abstracciones. En ese punto, es solo intento. La idea de meta-meta-clase no significa mucho; es una metaclase para las metaclases, lo cual es tonto pero técnicamente posible. Sin embargo, es solo una clase.


Editar

"¿Son clases que crean metaclases realmente tan tonta? ¿De qué manera su utilidad correr de repente?"

Una clase que crea una clase está bien.Eso es practicamente todo. El hecho de que la clase objetivo sea una metaclase o una superclase abstracta o una clase concreta no importa. Las metaclases hacen clases. Podrían hacer otras metaclases, lo cual es extraño, pero siguen siendo solo clases de metaclases.

La utilidad "de repente" se acaba porque no hay nada real que necesite (o pueda escribir) en una metaclase que haga otra metaclase. No es que "de repente" se vuelva tonto. Es que no hay nada útil allí.

Como siembro, no dude en investigarlo. Por ejemplo, en realidad escribe una metaclase que construye otra metaclase. Que te diviertas. Puede haber algo útil allí.

El objetivo de OO es escribir definiciones de clase que modelen entidades del mundo real. Como tal, una metaclase a veces es útil para definir aspectos transversales de varias clases relacionadas. (Es una forma de hacer un poco de Programación Orientada al Aspecto.) Eso es todo lo que una metaclase puede hacer; es un lugar para mantener algunas funciones, como __new__(), que no son partes adecuadas de la clase en sí.

+0

respeto sus puntos. No debería haber equiparado metaclases como patrones/roles, sino solo implementaciones de ellos. ¿Pero evitar la formalización porque podría ser difícil? ¿Las clases que crean metaclases son realmente tan tontas? ¿Cómo se termina su utilidad de repente? Incluso las metaclases exhiben similitudes. –

+0

@ mike.amy: por "duro" quise decir incomprensible. No es "un poco desafiante". Es muy difícil, a veces imposible, desenredar una serie de patrones de diseño bien pensados ​​en formalismos. Algunas buenas decisiones de diseño son hábitos y difíciles de formalizar. –

18

Esto me recuerda la eterna búsqueda en la que algunas personas parecen estar para hacer una "implementación genérica de un patrón". Al igual que una fábrica que puede crear cualquier objeto (including another factory), o un marco de inyección de dependencia de propósito general que es mucho más complejo de administrar que simplemente escribir código que realmente hace algo.

Tuve que lidiar con las personas que intentaban la abstracción hasta el punto de mirar el ombligo cuando dirigía el proyecto de Zend Framework. Rechacé un montón de propuestas para crear componentes que no hacían nada, solo eran implementaciones mágicas de patrones de GoF, como si el patrón fuera un objetivo en sí mismo, en lugar de un medio para alcanzar un objetivo.

Hay un punto de rendimientos decrecientes para la abstracción. Alguna abstracción es genial, pero finalmente necesitas escribir código que haga algo útil.

De lo contrario, es turtles all the way down.

+1

+1 para tortugas! – Seth

+1

Tenemos que idear un patrón arquitectónico de Mundodisco –

+0

Tu publicación me recuerda a la [máquina de Von Neumann] (https://en.wikipedia.org/wiki/Monolith_ (Space_Odyssey)), también conocida como los Monolitos, de la serie Space Odyssey. –

6

Durante la conferencia Historia de los lenguajes de programación en 2007, Simon Peyton Jones comentó que Haskell permite la meta programación a través de Type Classes, pero que realmente se trata de tortugas hasta el fondo. Puede meta-meta-meta-meta, etc. programa en Haskell, pero que nunca ha oído hablar de nadie que use más de 3 niveles de indirección.

Guy Steele señaló que es lo mismo en Lisp y Scheme. Puedes hacer meta-programación usando backticks y evals (puedes pensar en un backtick como un Python lambda, un poco), pero nunca ha visto más de 3 backticks usados.

Es de suponer que han visto más códigos que tú o yo, por lo que es una pequeña exageración decir que nadie ha ido más allá de 3 niveles de meta.

Si lo piensas bien, la mayoría de las personas nunca usa meta-programación, y dos niveles son bastante difíciles de entender. Supongo que tres es casi imposible, y el último tipo en probar cuatro terminó en un manicomio.

+0

Realmente sientes como si estuvieras volviéndote loco tratando de alcanzar más allá de algunos niveles. +1 para la mención de asilo. – Triptych

1

Desde que entendí por primera vez las metaclases en Python, me preguntaba "¿qué se puede hacer con una clase meta-meta?". Hace al menos 10 años, y ahora, hace apenas un par de meses, me quedó claro que hay un mecanismo en la creación de clases de Python que en realidad implica una clase "meta-meta". Y, por lo tanto, es posible tratar de imaginar algún uso para eso.

Para recapitular instanciación de objetos en Python: Siempre que uno instancia un objeto en Python "llamando" a su clase con la misma sintaxis utilizada para llamar a una función normal, __new__ y __init__. Lo que "orquesta" la invocación de estos métodos en la clase es exactamente el método class class __call__. Por lo general, cuando uno escribe una metaclase en Python, se personaliza el método __new__ o __init__ de la metaclase.

Así, resulta que al escribir una clase de "meta-meta" uno puede personalizar su método __call__ y así controlar los parámetros pasados ​​y para __new__ y __init__ métodos de la metaclase, y si algún otro código ha de ser llamado antes de después de esos. Lo que resulta al final es que las metcalsas mismas suelen estar codificadas y solo se necesitan unas pocas, incluso si se trata de proyectos muy grandes. Por lo tanto, cualquier personalización que se pueda realizar en la llamada "meta meta" generalmente se realiza directamente en la metaclase. Y ellos, hay otros usos menos frecuentes para las metaclases de Python: uno puede personalizar un método __add__ en una metaclase para que las clases definidas sean "Admitibles" y crear una clase derivada que tenga las dos clases añadidas como superclases . Ese mecanismo es perfectamente válido también con metaclases, por lo tanto, solo que "tenemos un código real", sigue un ejemplo de clase "meta-meta" que permite componer "metaclases" para una clase simplemente agregándolas a la declaración de clase :

class MM(type): 
    def __add__(cls, other): 
     metacls = cls.__class__ 
     return metacls(cls.__name__ + other.__name__, (cls, other), {}) 

class M1(type, metaclass=MM): 
    def __new__(metacls, name, bases, namespace): 
     namespace["M1"] = "here" 
     print("At M1 creation") 
     return super().__new__(metacls, name, bases, namespace) 

class M2(type, metaclass=MM): 
    def __new__(metacls, name, bases, namespace): 
     namespace["M2"] = "there" 
     print("At M2 creation") 
     return super().__new__(metacls, name, bases, namespace) 

Y podemos ver que el trabajo en la consola interactiva:

In [22]: class Base(metaclass = M1 + M2): 
    ...:  pass 
    ...: 
At M1 creation 
At M2 creation 

Tenga en cuenta que tan diferentes metaclases en Python suelen ser difíciles de combinar, en realidad esto puede ser útil al permitir que un usuario hizo metaclass que se combinará con el de una biblioteca o stdlib, sin que este tenga que declararse explícitamente como principal del anterior:

In [23]: import abc 

In [24]: class Combined(metaclass=M1 + abc.ABCMeta): 
    ...:  pass 
    ...: 
At M1 creation 
Cuestiones relacionadas