metaclass - clear variables python - ¿Qué son las metaclases en Python?

reiniciar variables python / python / oop / python-class / python-datamodel

En Python,¿qué son las metaclases y para qué las utilizamos?

U11-Forward



Answer #1

Una metaclase básica,que no hace nada,le gustaría:

class Meta(type):

    def __prepare__(metaclass, cls, bases):
        return dict()

    def __new__(metacls, cls, bases, clsdict):
        return super().__new__(metacls, cls, bases, clsdict)
class Person:
    weight = ValidateType('weight', int)
    age = ValidateType('age', int)
    name = ValidateType('name', str)

Una simple metaclase puede resolver ese problema:

class Person(metaclass=Validator):
    weight = ValidateType(int)
    age = ValidateType(int)
    name = ValidateType(str)
class Validator(type):
    def __new__(metacls, cls, bases, clsdict):
        # buscar clsdict buscando descriptores ValidateType
        for name, attr in clsdict.items():
            if isinstance(attr, ValidateType):
                attr.name = name
                attr.attr = '_' + name
        # crea la clase final y devuélvela
        return super().__new__(metacls, cls, bases, clsdict)

Una muestra de:

p = Person()
p.weight = 9
print(p.weight)
p.weight = '9'
9
Traceback (most recent call last):
  File "simple_meta.py", line 36, in <module>
    p.weight = '9'
  File "simple_meta.py", line 24, in __set__
    (self.name, self.type, value))
TypeError: weight must be of type(s) <class 'int'> (got '9')

La clase 'ValidateType' como referencia:

class ValidateType:
    def __init__(self, type):
        self.name = None  # será establecido por metaclase
        self.attr = None  # será establecido por metaclase
        self.type = type
    def __get__(self, inst, cls):
        if inst is None:
            return self
        else:
            return inst.__dict__[self.attr]
    def __set__(self, inst, value):
        if not isinstance(value, self.type):
            raise TypeError('%s must be of type(s) %s (got %r)' %
                    (self.name, self.type, value))
        else:
            inst.__dict__[self.attr] = value