Python 类的自定义双星运算符?

Python 类的自定义双星运算符?,python,class,python-3.x,magic-methods,Python,Class,Python 3.x,Magic Methods,如何实现用于解包的自定义双星运算符(**),类似于使用单星运算符(*)进行解包的方式 例如: class PlayerManager(object): def __init__(self, players=None): self.players = players or [] # Made up method to support ** operator def __dict_iter__(self): for player in se

如何实现用于解包的自定义双星运算符(
**
),类似于使用单星运算符(
*
)进行解包的方式

例如:

class PlayerManager(object):

    def __init__(self, players=None):
        self.players = players or []

    # Made up method to support ** operator
    def __dict_iter__(self):
        for player in self.players:
            yield get_steamid(player), player

def print_players(**players):
    print(players)

player_manager = PlayerManager([list, of, players])
print_players(**player_manager)
输出:

{
    'STEAM_0:0:02201': <Player object at 0x0000000000>,
    'STEAM_0:0:10232': <Player object at 0x0000000064>,
    'STEAM_0:0:73602': <Player object at 0x0000000128>
}
{
“STEAM_0:0:02201”:,
“STEAM_0:0:10232”:,
“蒸汽_0:0:73602”:
}
执行以下操作。从技术上讲,语言文档没有指定使用了哪些
Mapping
方法,因此假设您只需要当前实现使用的一些子集是个坏主意:

如果语法**表达式出现在函数调用中,则表达式必须计算为映射,其内容将被视为附加关键字参数。如果关键字同时出现在表达式和显式关键字参数中,则会引发TypeError异常

因此,如果您实现了
映射
ABC,那么无论它是否依赖于
.items()
、直接迭代和
\u getitem\uuuu
调用等,您都肯定拥有正确的接口

仅供参考,在检查时,CPython 3.5中的行为肯定取决于您如何实现
映射
(如果您继承自
dict
,它使用一个优化路径直接访问
dict
内部,如果您不这样做,它将迭代
.keys()
,并在运行时查找每个键)。所以,是的,不要偷工减料,实施整个ABC。由于默认实现继承自
映射
ABC及其父级,因此只需以下几项即可实现:

class MyMapping(Mapping):
    def __getitem__(self, key):
        ...
    def __iter__(self):
        ...
    def __len__(self):
        ...

您继承的默认实现在某些情况下可能是次优的(例如,
会做一些涉及迭代和查找的半邪恶的事情,其中直接访问器可能会更快,这取决于内部),因此如果您将其用于其他目的,我建议用优化的版本覆盖它们。

正如@ShadowRanger所说,实现映射。下面是一个例子:

from collections.abc import Mapping

class Foo(Mapping):
    def __iter__(self):
        yield "a"
        yield "b"

    def __len__(self):
        return 2

    def __getitem__(self, item):
        return ord(item)

f = Foo()

print(*f)
print(dict(**f))
程序输出:

a b
{'a': 97, 'b': 98}

非常感谢,我接受了@codeape的回答,因为它清楚地表明了我需要做什么才能使我的班级支持
**
,但我确实投了你一票@马库斯梅斯卡宁:奇怪。你写这篇文章的时候,我正在详细说明,但没有通知我(我仍然没有关于它的评论提醒,而且代表在投票后几分钟内没有出现)。嗯。不管怎样。@ShadowRanger:你知道是哪个CPython实现了这个吗?希望向C端classAh添加对
**
的支持,