Как запустить @property getter условно, например, для целей фильтрации - PullRequest
0 голосов
/ 02 февраля 2019

У меня есть список словарей для свойства класса, который реализуется с помощью @property getter и setter.Тем не менее, я хотел бы иметь условный геттер или альтернативную реализацию с тем же именем.

У меня есть мой класс и @property с геттером и сеттером, работающим и проверенным модулем.Единственное, чего не хватает, это питонной реализации условного геттера для целей фильтрации.

Я посмотрел официальную документацию, погуглил, очень кратко посмотрел на некоторый исходный код Pandas.

# python v3.7.2
# simplified code

class MyClass:
    def __init__(self)
    self.uuid = str(uuid.uuid4())
    self.my_dict = []

@property
def mydict(self)
    return self._mydict

@mydict.setter
def mydict(self, inputdict)
    self._mydict.append({
        'target': inputdict.get('target').uuid})

A, B, C = MyClass ()

A.mydict = {'target': B}

print (A.mydict)

[{'target': B.uuid}]

A.mydict = {'target': C}

print (A.mydict)

[{'target': B.uuid}, {'target': C.uuid}]

И я хочу печатать

(A.mydict (target= B))

[{'target': B.uuid}]

, что потребовало бы дополнительного кодирования для обработки предполагаемых аргументов ключевого слова в получателе, но

TypeError: объект 'list' не может быть вызван

1 Ответ

0 голосов
/ 07 февраля 2019

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

Я публикую и классовые, и модульные тесты поведения.Скорее всего, этот код подвержен ошибкам, но он выполняет свою работу для текущей версии любимого проекта.Любые советы и потенциальные проблемы с юзабилити и масштабированием приветствуются.

class Correspondence(dict):
"""A class for Correspondence data structure, see Chapter 2 of the book."""

def update(self, *args, **kwargs):
    """Update the correspondence object with the unique keys."""
    try:
        keyid = args[0]['target'] + args[0]['source'] + args[0]['condition']
        self[keyid] = args[0]
    except KeyError:
        raise TypeError('The input should contain source, target, \
            condition and truthvalue as keys of the input dictionary')

def filter(self, source=None, target=None, condition=None, truthvalue=None):
    """Filter Correspondence object. (target ⇐ source))

    Input:
        source:     filtering condition, source
        target:     filtering condition, target
        condition:  filtering conidtion, correspondence condition
        truthvalue: filtering condition, truthvalue excluding 
    Output:
        output: a Correspondence instance
    """

    filters = {
        'source': source,
        'target': target,
        'condition': condition,
        'truthvalue': truthvalue}
    filters = {k: v for k, v in filters.items() if v is not None}


    if not bool(filters):
        return self
    else:
        _correspondence = copy.deepcopy(self)
        # iterate over filters, followed by iteration over items
        # if the conditions are not satisfied, then items are removed
        # matrix-based computation would be more efficient,
        # but would do for now unless performance issues
        for filter_key, filter_value in filters.items():
            for key, value in self.items():
                if value[filter_key] is not filter_value:
                    del _correspondence[key]

        return _correspondence

Юнит-тесты

def test_correspondence_structure_and_methods(self):
    # check if correspondence has the right structure
    BA_correspondence = {
        'source': 'A.uuid',
        'target': 'B.uuid',
        'condition': 'the condition',
        'truthvalue': 'true'}

    CA_correspondence = {
        'source': 'A.uuid',
        'target': 'C.uuid',
        'condition': 'the condition',
        'truthvalue': 'true'}

    CA_correspondence_wrong = {
        'sources': 'A.uuid',          # the key should be "source"
        'target': 'C.uuid',
        'condition': 'the condition',
        'truthvalue': 'true'}

    BA_correspondence_upd = {
        'source': 'A.uuid',
        'target': 'B.uuid',
        'condition': 'the condition',
        'truthvalue': 'unverifiable'}

    correspondence = fabric.Correspondence()

    # test if Correspondence.update() processes the right data
    self.assertRaises(
        TypeError,
        correspondence.update,
        CA_correspondence_wrong)

    correspondence.update(BA_correspondence)
    # (B ⇐ A)
    self.assertDictEqual(
        {'B.uuidA.uuidthe condition': BA_correspondence},
        correspondence)

    # (B ⇐ A) ⋅ (C ⇐ A)
    correspondence.update(CA_correspondence)
    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence)

    # updated truthvalue with the same source, target, and condition
    # (B ⇐ A) ⋅ (C ⇐ A)
    correspondence.update(BA_correspondence_upd)
    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence)

    # filter correspondence
    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence.filter())

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd},
        correspondence.filter(target='B.uuid'))

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence.filter(source='A.uuid'))

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence.filter(condition='the condition'))

    self.assertDictEqual(
        {
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence.filter(truthvalue='true'))

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd},
        correspondence.filter(source='A.uuid', truthvalue='unverifiable'))

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd},
        correspondence.
            filter(source='A.uuid').filter(truthvalue='unverifiable'))
...