Как интегрировать метод в класс? - PullRequest
2 голосов
/ 08 октября 2019

Пожалуйста, потерпите меня - ООП и Python являются для меня очень новыми вещами.

У меня есть класс, который выглядит так:

class Offer():
    def __init__(self, active=False, kind=None, added=None,
                area=None, city=None, street=None, coords=None, phone=None,
                size=None, ... many more attributes
                ):
        self.active = active
        self.added = added
        self.kind = kind
        self.area = area
        self.city = city
        self.street = street
        self.coords = coords
        self.phone = phone
        self.size = size
        ...
        many more attributes

Я хотел бы иметь эту структурукак вложенный dict, поэтому я добавил это в Offer ()

# continue of previous block

@property
    def dictionary(self):
        d = {
            'active' : self.active,
            'added' : self.added,
            'kind' : self.kind, 
            'address' : {
                'area' : self.area,
                'city' : self.city,
                'street' : self.street,
                'coords' : self.coords
            },
            'params' : {
                'size' : self.size,
                'phone' : self.phone,
            }
            ...
            many more nested dict
        return d

Я хочу, чтобы пользователь использовал этот класс следующим образом:

>>> a = Offer(active=True, added=12.11.19, kind="kind", city="some city", street="some street", phone=123456789)

>>> print(a.dictionary)

{ 'active' : True, 'added' : 12.11.19, 'kind' : "kind", 'address' : { 'city' : "some city", 'street' : "some street"    }, 'params' : { 'phone' : 123456789 } }

Я хочучтобы возвращать только те значения, которые не None и использовать мою пользовательскую иерархию для данных.

Я обнаружил, что этот фрагмент кода, который прекрасно работает для того, что мне нужно.

a = Offer(phone=123456789, size=50, city="city", kind='kind')

def remove_none(obj):
  if isinstance(obj, (list, tuple, set)):
    return type(obj)(remove_none(x) for x in obj if x is not None)
  elif isinstance(obj, dict):
    return type(obj)((remove_none(k), remove_none(v))
      for k, v in obj.items() if k is not None and v is not None)
  else:
    return obj

print(remove_none(a.dictionary))

Мой вопрос: как мне интегрировать remove_none с @property, чтобы он выполнялся автоматически?

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

1 Ответ

0 голосов
/ 08 октября 2019

Сначала дополнительная информация. Требуемое для вашего класса представление dict уже может быть найдено с помощью vars(object) или object.__dict__.

>>> class Foo:
...     def __init__(self, x=None, y=10, z=20):
...         self.x = x
...         self.y = y
...         self.z = z
...
>>> f1 = Foo()
>>> f2 = Foo(1, 2, 3)
>>> vars(f1)
{'x': None, 'y': 10, 'z': 20}
>>> vars(f2)
{'x': 1, 'y': 2, 'z': 3}
>>> f1.__dict__
{'x': None, 'y': 10, 'z': 20}

Генерация представления dict объекта может бытьуправляется реализацией __setattr__ внутри класса.

>>> class Foo:
...     def __init__(self, x=None, y=10, z=20):
...         self.x = x
...         self.y = y
...         self.z = z
...     def __setattr__(self, name, value):
...         if value is not None:
...             self.__dict__[name] = value
...
>>> f1 = Foo()
>>> f2 = Foo(1, 2, 3)
>>> vars(f1)
{'y': 10, 'z': 20}
>>> vars(f2)
{'x': 1, 'y': 2, 'z': 3}
>>> f1.__dict__
{'y': 10, 'z': 20}

Поскольку вам нужна пользовательская структура dict, вы можете перебрать все переменные экземпляра класса и добавить значения в dict, если значение равноне None.

@property
def dictionary(self):
    d = {
        'address': {}, 
        'params': {}
    }
    address = {'area', 'city', 'street', 'coords'}
    params = {'size', 'phone'}

    for k, v in self.__dict__.items():
        if v is None:
            continue

        if k in address:
            d['address'][k] = v
        elif k in params:
            d['params'][k] = v
        else:
            d[k] = v

    return d
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...