Descriptor with meta class vs traditional

Asked

Viewed 53 times

0

I’ve been watching the videos (example) by Luciano Ramalho on Descriptors with metaclass.

I wanted to know the advantage of this model in relation to the more traditional implementation of Descriptors as that example in the documentation:

class RevealAccess(object):
    """A data descriptor that sets and returns values
       normally and prints a message logging their access.
    """

    def __init__(self, initval=None, name='var'):
        self.val = initval
        self.name = name

    def __get__(self, obj, objtype):
        print('Retrieving', self.name)
        return self.val

    def __set__(self, obj, val):
        print('Updating', self.name)
        self.val = val

>>> class MyClass(object):
...     x = RevealAccess(10, 'var "x"')
...     y = 5
...
>>> m = MyClass()
>>> m.x
Retrieving var "x"
10
>>> m.x = 20
Updating var "x"
>>> m.x
Retrieving var "x"
20
>>> m.y
5

I made a test and to me it seemed to work equal. I also noticed that in the example of documentation the methods getattr and setattr are not used as in example luciano:

class Quantidade(object):
    def __init__(self)
        self.set_nome(self.__class__.__name__, id(self))

    def set_nome(self, prefix, key):
        self.nome_alvo = '%s_%s' % (prefix, key)

    def __get__(self, instance, owner):
        return getattr(instance, self.nome_alvo)

    def __set__(self, instance, value):
        if value > 0:
            setattr(instance, self.nome_alvo, value)
        else:
            raise ValueError('valor deve ser > 0')


class ModeloMeta(type):
    def __init__(cls, nome, bases, dic):
        super(ModeloMeta, cls).__init__(nome, bases, dic)
        for chave, attr in dic.items():
            if hasattr(atr, 'set_nome'):
                attr.set_nome('__' + nome, chave)

class Modelo(object):
    __metaclass__ = ModeloMeta


class ItemPedido(Modelo):
    peso = Quantidade()
    preco = Quantidade()

    def __init__(self, descricao, peso, preco):
        self.descricao = descricao
        self.peso = peso
        self.preco = preco

1 answer

2


In fact I was completely outdated with regard to the new features of python3.6+. Python3.6 introduced the descriptor protocol object.__set_name__(self, owner, name) called at the time the class is created. Therefore, I think it is no longer necessary to use metaclass to work with Descriptors from Python3.6+. Follows publishing I used to read about the theme, it even makes comparisons between the new version and the legacy mode.

  • 2

    yes- that’s right - the __set_name__ reduces the most obvious use for metaclasses, and their existence makes the use of the same optional in most cases.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.