Frage

Ich habe kürzlich entdeckt metaclasses in Python.

Im Grunde eine Metaklasse in Python ist eine Klasse, die eine Klasse erstellt. Es gibt viele nützliche Gründe, warum Sie wollen würde, dies zu tun - jede Art von Klasse Initialisierung zum Beispiel. Registrieren von Klassen auf Fabriken, komplexe Validierung von Attributen, zu verändern, wie die Vererbung funktioniert, usw. All dies wird nicht nur möglich, sondern einfach.

Aber in Python, metaclasses sind auch schlicht Klassen. Also begann ich mich gefragt, ob die Abstraktion sinnvollerweise höher gehen könnte, und es scheint mir, dass es kann und dass:

  • a metaclass entspricht oder implementiert eine Rolle in einem Muster (wie in GOF Muster Sprachen).
  • ein Meta-Metaklasse ist das Muster selbst (wenn wir zulassen, dass es Tupel von Klassen darstellen abstrakte Rollen zu schaffen, anstatt nur eine einzige Klasse)
  • ein Meta-Meta-Metaklasse ist eine Muster Fabrik , die zu den GOF Mustern Gruppierungen entsprechen, z.B. Creational, Strukturelle, Behavioral. Eine Fabrik, wo Sie einen Fall von einer bestimmten Art von Problem beschreiben könnten und es würde Ihnen eine Reihe von Klassen geben, die es zu lösen.
  • ein Meta-Meta-Meta-Metaklasse (soweit ich gehen könnte), ist eine Muster Fabrik Fabrik , eine Fabrik, auf der Sie vielleicht die Art des Problems beschreiben könnten und es würde Sie eine Musterfabrik zu stellen.

Ich habe ein paar Sachen über diese online gefunden, aber meistens nicht sehr nützlich. Ein Problem ist, dass verschiedene Sprachen definieren metaclasses etwas anders.

Hat jemand anderes metaclasses wie dies in Python verwendet / anderswo, oder dies in der freien Natur verwendet gesehen oder darüber nachgedacht? Was sind die Analoga in anderen Sprachen? Z.B. in C ++, wie tief kann die Vorlage Rekursion gehen?

Ich würde sehr gerne, es weiter zu erforschen.

War es hilfreich?

Lösung

Das Klassensystem in Smalltalk ist interessant zu studieren. In Smalltalk, alles ist ein Objekt und jedes Objekt eine Klasse hat. Dies bedeutet nicht, dass die Hierarchie bis ins Unendliche geht. Wenn ich mich richtig erinnere, geht es so etwas wie:

5 -> Integer -> Integer-Klasse -> Metaclass -> Metaclass Klasse -> Metaclass -> ... (es Loops)

Wo '->'. Bezeichnet "ist eine Instanz von"

Andere Tipps

Das erinnert mich an die ewige Suche einige Leute zu sein scheinen zu machen „generische Implementierung eines Musters.“ Wie eine Fabrik, die jedes Objekt erstellen ( einschließlich einer anderen Fabrik ) oder ein Mehrzweck Dependency Injection-Framework, die weitaus komplexer ist einfach zu handhaben als das Schreiben von Code, dass tatsächlich tut etwas.

hatte ich mit Leuten auf Abstraktion bis hin zum Nabelschau Absicht zu tun, als ich das Zend Framework Projekt zu verwalten. Ich drehte mich um ein Bündel von Vorschlägen unten Komponenten zu schaffen, die nichts zu tun haben, sie waren nur magische Implementierungen von GoF-Muster, als ob das Muster an sich schon ein Ziel wäre, statt ein Mittel, um ein Ziel.

Es gibt einen Punkt der Renditen für Abstraktion zu verringern. Einige Abstraktion ist groß, aber schließlich müssen Sie Code schreiben, etwas Nützliches tut.

Ansonsten einfach es ist Schildkröten den ganzen Weg hinunter .

Um Ihre Frage zu beantworten: no.

Fühlen Sie sich frei, um es weiter zu erforschen.

Beachten Sie jedoch, dass Sie Entwurfsmuster verschmelzt haben mit Code (die nur Ideen sind) (das ist eine Implementierung.)

Guter Code spiegelt oft eine Reihe von Design-Muster Verriegelung. Es gibt keine einfache Möglichkeit für formalize dieser. Das Beste, was Sie tun können, ist ein schönes Bild, gut geschriebene Docstrings und Methodennamen, die die verschiedenen Entwurfsmuster widerspiegeln.

Beachten Sie auch, dass eine Meta-Klasse eine Klasse ist. Das ist eine Schleife. Es gibt keine höhere Abstraktionen. An diesem Punkt ist es nur Absicht. Die Idee der Meta-Meta-Klasse bedeutet nicht viel - es ist eine Meta-Klasse für Meta-Klassen, die dumm ist, aber technisch möglich. Es ist alles nur eine Klasse, aber.


Bearbeiten

„sind Klassen, die metaclasses wirklich so dumm? Wie wird sie Nutzen plötzlich leer? Erstellen“

Eine Klasse, die eine Klasse erstellt, ist in Ordnung. Das wars so ziemlich. Die Tatsache, dass die Zielklasse ist eine Meta-Klasse oder eine abstrakte Superklasse oder eine konkrete Klasse spielt keine Rolle. Metaclasses machen Klassen. Sie könnten andere metaclasses machen, was seltsam ist, aber sie sind immer noch nur Metaclasses Klassen zu machen.

Das Dienstprogramm „plötzlich“ läuft, weil es keine wirkliche Sache Sie brauchen (oder sogar schreiben) in einer Metaklasse, die eine andere metaclass macht. Es ist nicht, dass es „plötzlich“ albern wird. Es ist, dass es nichts nützlich es.

Wie ich Samen, fühlen sich frei, um es zu erforschen. Schreiben Sie zum Beispiel tatsächlich eine Metaklasse, die eine andere metaclass baut. Habe Spaß. Es könnte etwas nützlich sein.

Der Punkt der OO ist zu Klassendefinitionen, dieses Modell der realen Welt Entitäten zu schreiben. Als solches ist ein Metaklasse manchmal praktisch Querschnittsaspekte von mehreren verwandten Klassen zu definieren. (Es ist ein Weg, um etwas Aspect-Oriented Programming zu tun.) Das ist alles ein metaclass wirklich tun kann; es ist ein Ort, um ein paar Funktionen, wie __new__() zu halten, die sich nicht richtig Teile der Klasse sind.

Während der Geschichte der Programmiersprachen Konferenz im Jahre 2007, kommentiert Simon Peyton Jones, dass Haskell Meta-Programmierung mit Typklassen erlaubt, aber dass seine wirklich Schildkröten ganz nach unten. Sie können Meta-Meta-Meta-Meta etc Programm in Haskell, aber dass er noch nie von jemandem mit mehr als 3 Dereferenzierungsebenen gehört.

Guy Steele wies darauf hin, dass es das gleiche in Lisp und Scheme. Sie können Meta-Programmierung tun und Backticks evals mit (Sie ein Graviszeichen als Python-Lambda denken können, ein bisschen), aber er hat nie mehr als 3 Backticks verwendet gesehen.

Vermutlich haben sie mehr Code als Sie gesehen oder ich je hat, so ist es nur eine leichte Übertreibung zu sagen, dass niemand jemals über 3 Ebenen von Meta gegangen ist.

Wenn man darüber nachdenkt, haben die meisten Menschen überhaupt nicht verwenden Meta-Programmierung und zwei Ebenen ist ziemlich schwer, den Kopf herum zu wickeln. Ich würde vermuten, dass drei fast unmöglich ist, und das, dass im letzten Mann zu versuchen, vier in einer Irrenanstalt gelandet ist.

Da, wenn ich verstand metaclasses in Python zuerst, ich fragte mich: „Was mit einer Meta-Meta-Klasse getan werden könnte?“. Dies ist zumindest vor 10 Jahren - und jetzt, nur ein paar Monate her, es wurde für mich klar, dass es in Python-Klasse Schaffung eines Mechanismus ist, der eigentlich ein „Meta-Meta“ Klasse beinhaltet. Und deshalb ist es möglich, zu versuchen, einige Verwendung für die vorzustellen.

Zur Erinnerung Objektinstanziierung in Python: Jedes Mal, wenn man ein Objekt in Python instanziiert durch „Aufruf“ seine Klasse mit der gleichen Syntax für den Aufruf eine normale Funktion, die __new__ Klasse und __init__. Was „orchestriert“ die Berufung dieser Methoden auf die Klasse ist genau die __call__ Methode class'metaclass. Normalerweise, wenn man schreibt eine Metaklasse in Python, entweder die __new__ oder __init__ Methode des metaclass angepasst ist.

Also, es stellt sich heraus, dass eine „Meta-Meta“ Klasse, indem er eine seine __call__ Verfahren anpassen kann und damit steuern, welche Parameter übergeben werden und die Metaklasse der __new__ und __init__ Methoden, und wenn ein anderer Code aufgerufen werden soll, bevor von nach denen. Was am Ende stellt sich heraus, dass metcalsses sich in der Regel fest einprogrammiert werden und man braucht nur wenige, wenn überhaupt, auch in sehr großen Projekten. So dass jede Anpassung, die auf dem „Meta-Meta“ Aufruf getan werden könnte, wird in der Regel direkt auf dem metaclass getan selbst.

Und sie gibt es jene andere, weniger häufige Verwendungen für Python metaclasses - man kann eine __add__ Methode in einem metaclass so anpassen, dass die Klassen, die sie definieren sind „addable“, und erstellen Sie eine abgeleitete Klasse die beiden hinzugefügt Klassen als Oberklassen haben. Dieser Mechanismus ist perfekt gültig mit metaclasses auch - deshalb so nur wir „einige aktuelle Code haben“, folgt ein Beispiel für „Meta-Meta“ Klasse, die man nur durch Hinzufügen von ihnen auf Klassendeklaration „metaclasses“ für eine Klasse zu komponieren erlaubt :

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)

Und wir können sehen, dass auf der interaktiven Konsole arbeiten:

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

, die als unterschiedliche metaclasses in Python sind in der Regel schwer zu kombinieren, kann dies tatsächlich nützlich sein, indem er einen Benutzer hergestellt metaclass ermöglicht, mit einer Bibliothek oder stdlib einem kombiniert werden, ohne dass dies eine ausdrücklich als Elternteil das erklärt zu haben, werden früher:

In [23]: import abc

In [24]: class Combined(metaclass=M1 + abc.ABCMeta):
    ...:     pass
    ...: 
At M1 creation
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top