métaclasse python et déclaration sqlalchemy

métaclasse python et déclaration sqlalchemy

Les métaclasses sont rarement utilisées sauf s'il s'agit de bibliothèques, mais elles sont utilisées dans SQLAlchemy, je les résumerai donc à titre de référence uniquement.

Une métaclasse est un type de classe. Dans le cas de python, le type de la classe définie par l'utilisateur est essentiellement type.

>>> class A(object):
>>>     pass
>>>
>>> type(A)
type

Les métaclasses autres que type peuvent être utilisées à des fins spéciales.

Ceci est utilisé dans la déclaration de SQL Alchemy comme une utilisation familière des métaclasses.

>>> from sqlalchemy.ext.declarative import declarative_base
>>> Base = declarative_base()
>>> type(Base)
<class 'sqlalchemy.ext.declarative.api.DeclarativeMeta'>

Avec déclarative, la définition de classe est automatiquement associée à la définition de table.

class User(Base):
    __tablename__ = 'user_account'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(Varchar(100))

En interne, il utilise sa propre méta-classe appelée sqlalchemy.ext.declarative.api.DeclarativeMeta, et intercepte le traitement au moment de la définition de la classe pour effectuer le traitement du mappage.

La définition de sqlalchemy.ext.declarative.api.DeclarativeMeta est la suivante. init est appelé lorsqu'une classe qui hérite de Base est créée et que la classe et la table y sont liées.

sqlalchemy/ext/declarative/api.py


class DeclarativeMeta(type):
    def __init__(cls, classname, bases, dict_):
        if '_decl_class_registry' not in cls.__dict__:
            _as_declarative(cls, classname, cls.__dict__)
        type.__init__(cls, classname, bases, dict_)

    def __setattr__(cls, key, value):
        _add_attribute(cls, key, value)

En python, il semble que l'utilisation de la métaclasse soit une méthode relativement courante lorsque vous voulez faire quelque chose automatiquement à partir de la définition de classe. Par exemple, la classe Form de wtforms fait à peu près la même chose.

Selon le cas d'utilisation, vous souhaiterez peut-être arrêter ce processus. Considérons un cas d'utilisation tel que l'association d'un objet Table créé par réflexion à partir de DB avec une classe créée par declarative_base. Dans de tels cas, le code suivant peut être utilisé.

from sqlalchemy import MetaData, Table
from sqlalchemy.ext.declarative import api, declarative_base
from sqlalchemy.ext.declarative.api import DeclarativeMeta


class_registry = {}
metadata = MetaData()
Base = declarative_base(class_registry=class_registry,
                        metadata=MetaData())


class MyMetaClass(DeclarativeMeta):
    def __init__(cls, classname, bases, dict_):
        #Ne pas associer à la table
        type.__init__(cls, classname, bases, dict_)

    @classmethod
    def create_class(cls, table_name, class_name, dbsession):
        tableobj = Table(table_name, metadata, autoload=True,
                         autoload_with=dbsession.bind)
        class_ = MyMetaClass(class_name, (Base), {})
        #Associez-le explicitement au tableau ci-dessous.
        class_.__tablename__ = tablename
        class_.__table__ = tableobj
        for c in tableobj.columns:
            setattr(class_, c.name, c)
        api.instrument_declarative(class_, class_registry, metadata)
        return class_

Recommended Posts

métaclasse python et déclaration sqlalchemy
Mémo de métaclasse Python3
[python] Compresser et décompresser
Itérateur et générateur Python
Paquets et modules Python
Intégration Vue-Cli et Python
Ruby, Python et carte
Utilisez SQL Alchemy et le multitraitement
entrée et sortie python
Métaclasse et isinstance
Python asyncio et ContextVar
Chiffrement et déchiffrement avec Python
3-3, chaîne Python et code de caractère
Série Python 2 et série 3 (édition Anaconda)
Python et matériel - Utilisation de RS232C avec Python -
Python sur Ruby et Ruby en colère sur Python
Indentation Python et format de chaîne
division des nombres réels python (/) et division des nombres entiers (//)
Å (Ongustorome) et NFC @ Python
Apprenez à connaître les packages et les modules Python
[Python] Comment jouer avec les variables de classe avec décorateur et métaclasse
# 2 [python3] Séparation et commentaire
Copie superficielle Python et copie profonde
Comment se connecter à diverses bases de données à partir de Python (PEP 249) et SQL Alchemy
Mémo tranche python et rubis
Installation de Python et grammaire de base
J'ai comparé Java et Python!
Copie superficielle Python et copie profonde
[Python] Mémorandum sur l'évitement des erreurs SQLAlchemy
À propos de Python, len () et randint ()
À propos de la date et du fuseau horaire Python
Installez Python 3.7 et Django 3.0 (CentOS)
Construction d'environnement Python et TensorFlow
Variables de classe et d'instance Python
Syntaxe Ruby et Python ~ branch ~
[Python] Python et sécurité-① Qu'est-ce que Python?
Pile et file d'attente en Python
Implémentation de Fibonacci et des nombres premiers (python)
bases de python: conditions et itérations
Opérateur de bits Python et somme logique
Module de débogage et de test Python
Liste Python et tapples et virgules
Variables Python et ID d'objet
Notation et générateur d'inclusion de liste Python
À propos de Python et des expressions régulières
Group_by avec sqlalchemy et sum
python avec pyenv et venv
Comment écrire une classe méta qui prend en charge à la fois python2 et python3
Unittest et CI en Python
Description et implémentation de Maxout (Python)
[python] Obtenir le quotient et le surplus
Fonctions de tri et de comparaison Python 3
[Python] Recherche de priorité de profondeur et recherche de priorité de largeur
Identité et équivalence: is et == en Python
Installation source et installation de Python
Python ou et et opérateur trap
Défiez Python3 et Selenium Webdriver
À propos des opérations Python et OS
Fonctions d'ordre supérieur et notation d'inclusion en Python