Übergeben Sie in der Python-Metaklasse den Vergleichsoperator als Zeichenfolge an die ORM-Methode, um die where-Klausel zu erstellen.

Ich habe meinen eigenen ORM-Mapper erstellt, aber den Prozess der Übergabe des Vergleichsoperators als Argument an die where-Methode implementiert. Es wäre schön, wenn Sie sich vorstellen könnten, wie man es wie folgt benutzt. Sie können jede Bedingung der where-Klausel intuitiver angeben.

Session.select('coulmn_name1', 'coulmn_name2').where(Model.id > 1, _and, Model.name == "Mike")

Wenn Sie "Model.id> 1" als Argument übergeben, wird normalerweise "True" oder "False" übergeben, und "** id" bedeutet, dass mehr als 1 ** nicht übergeben werden kann. Wenn Sie jedoch die spezielle Methode neu schreiben, können Sie das Argument übergeben, ohne es als Vergleichsoperator zu verarbeiten.

In dieser where-Methode wird nur der Prozess "Zurückgeben der where-Klausel als Zeichenfolge" implementiert. Es ist einfach zu tun, aber diese Implementierung zu kennen, erwies sich als nützlich für die Metaprogrammierung.

Ich denke, dass nützliche Informationen für solche Menschen erhalten werden können. In diesem Artikel wird die Metaprogrammierung selbst jedoch nicht erläutert. Wenn Sie sich mit Metaprogrammierung auskennen und ein Beispiel sehen möchten, hilft Ihnen dieser Artikel.

So erstellen Sie Ihr eigenes Modell

Wenn Sie eine Tabelle haben, die Personen mit dem Namen Person behandelt, deklarieren Sie das Personenmodell in der Klasse wie folgt.

from model_base import *

class Person(ModelBase):
    id = {'default': 1}
    name = {'default': 'Mike'}

Sie müssen lediglich die erforderlichen Spaltennamen in Ihrem Modell deklarieren. Geben Sie für den Anfangswert die Option im Wörterbuch an. Diesmal haben wir nur die Defalut-Option. Solange Sie ModelBase erben, wird das Modell automatisch zusammengestellt.

Wenn die Person-Klasse geladen wird, enthalten die Klassenfelder "id" und "name" keine Wörterbücher wie "{'default': 1}". Das Spaltenklassenobjekt wird automatisch von der Metaklasse eingeschlossen. Wenn Sie "default" sehen möchten, schreiben Sie einfach "pseron_instance.id.default".

Variablenname wird als Spaltenname behandelt

Deklarieren Sie den Spaltennamen ohne _ (Unterstrich) am Anfang des Klassenfelds. Wenn Sie _ (Unterstrich) als Präfix verwenden, wird es nicht als Spalte erkannt. Stellen Sie daher der erforderlichen Methode oder dem erforderlichen Feld _ (Unterstrich) als privat voran.

Eigentlich verwenden

Diesmal gibt die where-Methode die zusammengesetzte where-Klausel als Zeichenfolge zurück.

from person import *

if __name__ == '__main__':
    db_manager = DBManager()

    #Zusammenstellung der where-Klausel
    db_manager.where(Person.id > 1, "or", Person.name == 'Mike')
    #Einfach einzugeben, wenn mit lokalen Variablen vorbereitet
    _and = "and"
    _or = "or"
    db_manager.where(Person.id > 1, _and, Person.name == 'Mike')

    #Überprüfen Sie die Standardeinstellung
    person_A = Person()
    print("person_A.id = %s" % person_A.id)
    print("person_A.name = %s" % person_A.name)

    # Model.Colm-Objekt für ID, Modell.Fehler, da id den Spaltenwert enthält
    person_A = "Jane"
    print(Person.name.default)
    # print(person_A.name.default)
    # => AttributeError: 'str' object has no attribute 'name'

Modul zum Zusammenbau des Modells

Es sind vier Klassen vorzubereiten.

class Column():

    def __init__(self, column_name, dict):
        #Halten Sie Spaltennamen in Klassenvariablen
        self.column_name = column_name

        #Wird beim Empfang des Einstellwerts jeder Spalte festgelegt
        if dict is not None:
            for key, value in dict.items():
                if key == "default":
                    self.default = value

    def __setattr__(self, key, value):
        #Sie können den Spaltentyp überprüfen, indem Sie den Wert überprüfen und einen Fehler auslösen.
        self.__dict__[key] = value

    #Überlastvergleichsoperator
    def __eq__(self, other):
        return "%s = %s" % (self.column_name, other)

    def __ne__(self, other):
        return "%s != %s" % (self.column_name, other)

    def __lt__(self, other):
        return "%s < %s" % (self.column_name, other)

    def __gt__(self, other):
        return "%s > %s" % (self.column_name, other)

    def __le__(self, other):
        return "%s <= %s" % (self.column_name, other)

    def __ge__(self, other):
        return "%s >= %s" % (self.column_name, other)

class MetaModel(type):
    def __new__(cls, cls_name, cls_bases, cls_dict):
        for key, value in cls_dict.items():
            #Extrahieren Sie nur öffentliche Attribute
            if not(key.startswith("_")):
                #Säule(Modellklassenvariablen)Kann den Anfangswert von abrufen
                #Halten Sie den Variablennamen im Spaltenfeld
                cls_dict[key] = Column(key, value)
        return super().__new__(cls, cls_name, cls_bases, cls_dict)

class ModelBase(metaclass=MetaModel):
    #Wird sofort nach dem Erstellen einer Instanz aufgerufen
    def __init__(self):
        #Legen Sie den Standardwert für das Column-Objekt fest
        class_dict = self.__class__.__dict__
        for column_key, column_value in class_dict.items():
            #Extrahieren Sie nur öffentliche Attribute
            if not(column_key.startswith("_")):
                setattr(self, column_key, column_value.default)

class DBManager():
    def where(self, *args):
        statement = "WHERE"
        for arg in args:
            if arg.upper() in ["AND", "OR"]:
                statement += " %s " % arg.upper()
            else:
                statement += " %s " % arg
        print(statement)

Ich habe die Metaklasse auf ModelBase gesetzt. Dies ist so, dass Sie nur "MetaModel" schreiben müssen, anstatt "metaclass = MetaModel" in die Unterklasse zu schreiben. Zusätzlich wird hier die gemeinsame Verarbeitung des Modells beschrieben.

Informationen für jede Spalte werden von einer Instanz einer dedizierten Klasse verwaltet. Auf diese Weise können Sie eine automatische Verarbeitung wie die Validierung für jede Spalte implementieren. Wenn es keine dedizierte Klasse gibt, Spaltenklasse, können Sie nur Spaltenwerte übergeben.

#Ohne ModelBase
class MyModel(metaclass=MetaModel):
    pass

#Wenn Sie ModelBase haben
class MyModel(ModelBase):
    pass

Selbst wenn Sie Person nicht instanziieren, wird ModelMeta, die Metaklasse von Person, ausgeführt, wenn Person geladen wird. Daher wird ein Spaltenobjekt (eine Instanz) dynamisch erstellt und in der ID und dem Namen der Klassenfelder der Person festgelegt. Diese Spalte enthält den Standardwert von jedem in der Standardeinstellung des Instanzmitglieds.

Der Fluss dieses Spaltenobjekts wird im Klassenfeld Person festgelegt

  1. Laden Sie die Person-Klasse
  2. MetaModel wird ausgeführt
  3. Erhalten Sie den erwarteten Anfangswert des Klassenfelds der Person. Beispiel: {" default ": 1}
  4. Erstellen Sie ein Spaltenobjekt mit dem Argument {"default": 1}
  5. Registrieren Sie ein Column-Objekt im Diktat, bei dem es sich um eine Liste von Klassenattributen handelt.
  6. Überlassen Sie die Definition des Klassenfelds dem Metaklassentyp, der das übergeordnete Element von MetaModel ist.
  7. Setzen Sie ein Spaltenobjekt mit Metaklassentyp auf das Klassenfeld der Person

Unterschied zwischen Metaklasse und neuer Klasse

Eine Metaklasse namens MetaModel kann auch als reguläre Klasse definiert werden, anstatt als Metaklasse. In diesem Fall können Sie einfach ModelBase verwenden. In diesem Fall müssen Sie jedoch einmal eine Instanz erstellen. Ich denke, Sie sollten die Instanziierung ganz am Ende des Quellcodes schreiben, damit sie beim Laden des Moduls automatisch ausgeführt wird. Aber ich denke nicht, dass es eine gute Idee ist.

class Column():
    pass

class MetaModel(type):
    pass

class DBManager():
    pass

class ModelBase():
	pass

ModelBase()`

Der Grund, warum Sie eine Instanz einmal erstellen müssen, ist, dass "new" den Vorgang zum Erstellen einer Instanz ausführt. (Streng kurz zuvor. Ich verlasse die Generation separat.) Wichtig ist hier, um welche Art von Instanz es sich handelt. Eine Metaklasse ist eine Klasse zum Erstellen einer Klasse, dh einer Instanz der Metaklasse. Andererseits ist eine einfache Klasseninstanz ein Objekt, das aus einer normalen Klasse erstellt wurde. Normalerweise ist eine Instanz ein Produkt einer Klasse, aber wenn wir über Beziehungen sprechen, können wir die Ausdrucksinstanz in Metaklassen und Klassen verwenden.

Die folgenden zwei Beziehungen werden beide mit der Blaupause generiert. Die rechte Seite kann als Instanz angesehen werden.

Wenn Sie in diesem Sinne sehen, dass "new" das ist, was Sie tun, wenn Sie eine Instanz erstellen, ist der einfache Unterschied zwischen einer Metaklasse und einer Klasse "new" die Reihenfolge der Verarbeitung. Organisieren Sie den letzten auszuführenden Ausführungsauftrag.

** Ausführungsreihenfolge **

  1. Metaclass .__ new __
  2. Die Klasse wird erstellt
  3. Klasse .__ neu __
  4. Eine Instanz wird erstellt
  5. Klasse .__ init __
  6. Instanzvariablen werden gesetzt

Recommended Posts

Übergeben Sie in der Python-Metaklasse den Vergleichsoperator als Zeichenfolge an die ORM-Methode, um die where-Klausel zu erstellen.
Verwendung der Methode __call__ in der Python-Klasse
[Einführung in Python] Wie verwende ich den Operator in in der for-Anweisung?
Rufen Sie die Formel in der Excel-Datei als Zeichenfolge in Python ab
Die eval () -Funktion, die eine Zeichenfolge als Ausdruck in Python berechnet
So geben Sie eine Zeichenfolge in Python ein und geben sie unverändert oder in die entgegengesetzte Richtung aus.
Einbetten von Variablen in Python-Strings
Dynamisches Ersetzen der nächsten Methode in Python
So übergeben Sie das Ergebnis der Ausführung eines Shell-Befehls in einer Liste in Python
[Python] Ich habe versucht, den Typnamen als Zeichenfolge aus der Typfunktion abzurufen
Überprüfen Sie, ob die Zeichenfolge eine Zahl in Python ist
Analysieren Sie eine JSON-Zeichenfolge, die in eine Datei in Python geschrieben wurde
So konvertieren / wiederherstellen Sie einen String mit [] in Python
Ich möchte eine Variable in einen Python-String einbetten
[Python] So erweitern Sie Variablen in einer Zeichenfolge
[Python] Erstellt eine Methode zum Konvertieren von Radix in 1 Sekunde
[C / C ++] Übergeben Sie den in C / C ++ berechneten Wert an eine Python-Funktion, um den Prozess auszuführen, und verwenden Sie diesen Wert in C / C ++.
[Python] Programmieren, um die Nummer von a in einer Zeichenfolge zu finden, die eine bestimmte Anzahl von Malen wiederholt.
Wie kann man schnell die Häufigkeit des Auftretens von Zeichen aus einer Zeichenfolge in Python zählen?
Übergeben des Ausführungsergebnisses eines Shell-Befehls in einer Liste in Python (nicht blockierende Version)
Finden Sie die scheinbare Breite einer Zeichenfolge in Python heraus
Ändern Sie das Standardausgabeziel in eine Datei in Python
Ich habe versucht "Wie man eine Methode in Python dekoriert"
So generieren Sie eine Abfrage mit dem IN-Operator in Django
Wie man in Django die angezeigte lange Zeichenkette in der Mitte abkürzt ....
Beispiel für eine Python-Codelösung --1.6 Komprimierung von Zeichenketten
Führen Sie den Ausgabecode auf dem lokalen Webserver in Python als "A, gibt vor, B zu sein" aus
[Python] Erstellen Sie ein Programm, das Zeilenumbrüche in der Zwischenablage löscht. + Als Verknüpfung mit Fenstern registrieren
So bestimmen Sie die Existenz eines Selenelements in Python
Übergeben von Argumenten an Python-Skripte in SPSS Modeler Batch
So machen Sie einen String in Python zu einem Array oder ein Array zu einem String
[Einführung in Python] So teilen Sie eine Zeichenfolge mit der Funktion split
[Einführung in Python] So geben Sie eine Zeichenfolge in einer Print-Anweisung aus
So überprüfen Sie die Speichergröße einer Variablen in Python
Python: Verwenden Sie die im Zeichenfolgenformat definierten Variablen unverändert
So erhalten Sie eine Zeichenfolge aus einem Befehlszeilenargument in Python
Zeitzonenspezifikation beim Konvertieren einer Zeichenfolge in einen Datums- / Uhrzeittyp mit Python
So überprüfen Sie die Speichergröße eines Wörterbuchs in Python
Eine Funktion, die die Verarbeitungszeit einer Methode in Python misst
Im Python-Befehl zeigt Python auf Python3.8
4 Methoden zum Zählen der Anzahl von Ganzzahlen in einem bestimmten Intervall (einschließlich der imos-Methode) [Python-Implementierung]
6 Möglichkeiten zum Stringen von Objekten in Python
Erstellen Sie eine zufällige Zeichenfolge in Python
Wenn Sie einen Singleton in Python möchten, stellen Sie sich das Modul als Singleton vor
Hinweis: [Python3] Konvertiert datetime in eine Zeichenfolge in einem beliebigen Format
So installieren Sie das Python-Paket in einer lokalen Umgebung als allgemeiner Benutzer
Ich möchte das Ergebnis von "Zeichenfolge" .split () in Python stapelweise konvertieren
Ich möchte einen Teil der Excel-Zeichenfolge mit Python einfärben
So schreiben Sie eine Zeichenfolge, wenn Python mehrere Zeilen enthält
[Einführung in Python] So schreiben Sie eine Zeichenfolge mit der Formatierungsfunktion
[Einführung in Python] Eine ausführliche Erklärung der in Python verwendeten Zeichenkettentypen!
Ich habe ein Programm erstellt, um die Größe einer Datei mit Python zu überprüfen
Sortieren durch Angabe einer Spalte im Python Numpy-Array.
Bewegen Sie die Schildkröte an die Stelle, an der Sie mit der Maus mit der Schildkröte in Python klicken
<Python> Ein Quiz zum Batch-Konvertieren von Dateinamen, die durch eine bestimmte Zeichenfolge als Teil des Dateinamens getrennt sind
Methode zum Erstellen einer Python-Umgebung in Xcode 6
Schreiben Sie den Test in die Python-Dokumentzeichenfolge
[Python] So invertieren Sie eine Zeichenfolge
Generieren Sie eine Klasse aus einer Zeichenfolge in Python