python: 重载 ** dict 解包

python: Overloading ** dict unpacking

我希望能够从类似字典的对象中解压一个对象 class。

当前: f(**m.to_dict())

首选 f(**m)

如果 starstarprepare 存在,这将有效:

class M:
    #... __getitem__, __setitem__
    def __starstarprepare__(self):
        md = self.to_dict()
        return md

** 适用于任何映射类型。使 M 成为映射类型的一种方法是继承 collections.abc.Mapping 并实现 __getitem____iter____len__:

from collections.abc import Mapping

class M(Mapping):
    def __init__(self):
        self.a = 3
        self.b = 5

    def __getitem__(self, key):
        return getattr(self, key)

    def __iter__(self):
        yield 'a'
        yield 'b'

    def __len__(self):
        return 2


def foo(**kwargs):
    for k, v in kwargs.items():
        print(k, v)


m = M()
foo(**m)

如果您已经有一个 to_dict 方法,所有三个魔术方法都可以是相应 dict 方法的包装器。

class M(Mapping):
    def __init__(self):
        self.a = 3
        self.b = 5

    def to_dict(self):
        return {'a': self.a, 'b': self.b}

    def __getitem__(self, key):
        return self.to_dict()[key]

    def __iter__(self):
        return iter(self.to_dict())

    def __len__(self):
        return len(self.to_dict())

您可以使用 collections.abc.Mapping.

from collections.abc import Mapping

class M(Mapping):
    def __iter__(self):
        return iter(self.to_dict())
    def __getitem__(self, item):
        return self.to_dict()[item]
    def __len__(self):
        return len(self.to_dict())

@peter 的解决方案

class M:
    # ... __getitem__  and other functions
    def keys(self):
        k = self.to_dict().keys()
        return k