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添加对**
的支持,