Зарегистрируйте данные по свойствам класса, используя декораторы - PullRequest
0 голосов
/ 29 января 2019

Прежде всего, это НЕ о сериализации XML - это просто хороший пример использования в качестве примера.

Я хочу иметь возможность разметки свойств внутри класса, а затем иметь возможность чтения сериализаторомэти метаданные и использовать их.

Я смотрел на Класс с реестром методов, основанных на декораторах , но подход здесь, кажется, работает только с методами (не свойствами)и мне также нужно принять аргументы в декораторы разметки (OutputAsXmlAttribute & OutputAsXmlElement).

class MyXmlInvoice(object):

    @OutputAsXmlAttribute('invoiceNo', 'http://my.company.com/invoice-schema')
    @property
    def id(self) -> 'str':
        pass

    @id.setter
    def id(self, value: str):
        pass


    @OutputAsXmlElement('Price', 'http://my.company.com/invoice-schema')
    @property
    def price(self) -> 'int':
        pass

    @price.setter
    def price(self, value: int):
        pass


# This is the use case for the objects where MyXmlSerializer uses 
# the meta data on price & id to influence the serialization
xmlInvoice = MyXmlInvoice()
xmlInvoice.price = 3
xmlInvoice.id = "0001"

xmlSerializer = MyXmlSerializer()
xmlData = xmlSerializer.Serialize(xmlInvoice)

1 Ответ

0 голосов
/ 29 января 2019

Функция Python - это просто объект, который может получать дополнительные атрибуты.К сожалению, свойства не могут, поэтому вы должны развернуть их.Это означает, что вы можете начать с:

def OutputAsXmlElement(label, schema):
    def deco(p):
        f = p.fget if isinstance(p, property) else p
        f._label = label
        f._schema = schema
        f._iselement = True
        return p
    return deco

def OutputAsXmlAttribute(label, schema):
    def deco(p):
        f = p.fget if isinstance(p, property) else p
        f._label = label
        f._schema = schema
        f._iselement = False
        return p
    return deco

Затем через модуль inspect вы можете получить доступ к этим специальным атрибутам.Например, вот способ найти всех украшенных членов вашего примера класса с их меткой и схемой:

for x, y in ((x,y) for x,y in inspect.getmembers(xmlInvoice.__class__)
         if not x.startswith('__')):
    if isinstance(y, property):
        f = y.fget
    else:
        f = y
    print(x, getattr(f, '_label', None), getattr(f, '_schema', None), getattr(f, '_element', None))
...