首页 > 解决方案 > 如何将方法集成到类中?

问题描述

请多多包涵——OOP 和 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

我想将此结构作为嵌套字典,所以我已将其添加到 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 以便它自动执行?

也许我在这里想错了,但如果有人能指出我正确的方向,那将对我有很大帮助。

标签: pythonpython-3.xoop

解决方案


首先是一些额外的信息。已经可以使用vars(object)or找到您想要的类的 dict 表示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结构,因此您可以遍历类的所有实例变量,如果值不是 None,则将值添加到 dict。

@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

推荐阅读