对于我自己的用户定义的类,如何在可变参数函数中覆盖用于kwarg的`**`运算符?

问题描述 投票:2回答:1

我希望能够解压缩自己的类似于字典的类。

class FauxDict:
    def __getitem__(self, key):
        return 99
    def __iter__(self):
        return range(0, 1)
    def to_map(self):
        return map(lambda x: True, range(0, 2))

def bar(**kwargs):
    pass

dct = {"x":1, "y":2}
bar(**dct) # no error

dct = FauxDict()
bar(**dct) # error

dct = FauxDict()
bar(**dct.to_map()) # error

错误是:

bar(**dct) # error
TypeError: bar() argument after ** must be a mapping, not FauxDict

bar(**dct.to_map()) # error
TypeError: bar() argument after ** must be a mapping, not map

而且,从技术上讲,哪个python类可以作为映射?

python python-3.x variadic-functions
1个回答
0
投票

实现.keys().__getitem__()足以允许使用**扩展自定义类的实例。

cpython源代码的相关部分在使用ceval.c_PyDict_MergeEx中,因此在dict_merge中使用dictobject.c指出:

/ *我们为参数接受一个具体的字典对象,*或抽象的“映射”对象。对于前者,我们可以做*事情非常有效。对于后者,我们只要求*支持PyMapping_Keys()和PyObject_GetItem()。* /

事实上,实现这两种方法的工作符合您的预期:

class MyMapping:
    def __init__(self, d):
        self._d = d

    def __getitem__(self, k):
        return self._d[k]

    def keys(self):
        return self._d.keys()


def foo(a,b):
    print(f"a:{a}")
    print(f"b:{b}")

mm = MyMapping({"a":"A","b":"B"})
foo(**mm)

输出:

答:Ab:B

旁注:您的.keys()实现只需要返回一个可迭代的对象(例如,一个列表就可以了),而不必像上面为简单起见而使用的dict_keys对象。该行也可以是return list(self._d.keys()),没有问题。

© www.soinside.com 2019 - 2024. All rights reserved.