【问题标题】:python: applying ** operator on user-defined classpython:在用户定义的类上应用**运算符
【发布时间】:2018-05-18 07:28:15
【问题描述】:

我创建了一个自定义类,我想在实例上使用** 运算符将其传递给函数。我已经定义了__getitem____iter__,但是当我尝试f(**my_object) 时,我得到了

`TypeError: argument must be a mapping, not 'MyClass'`

为了使自定义类符合映射条件,最少需要哪些方法?

【问题讨论】:

  • ** 不是运算符。它是调用语法的一部分。你预计会发生什么?
  • 最简单的方法是继承dict
  • 我希望它能够解压我的对象,就像它对 dict 所做的那样。但是对象必须实现的方法是什么?
  • 你的类需要模拟一个类似映射的对象。正如@kindall 已经说过的,从dict 继承可能是最简单的解决方案。

标签: python parameter-passing overloading keyword-argument


【解决方案1】:

** 不是运算符,它是call syntax 的一部分:

如果语法**expression出现在函数调用中,则表达式必须计算为mapping,其内容被视为附加关键字参数。

因此,如果您的班级实现了Mapping methods,那么您应该很高兴。您需要的不仅仅是__getitem____iter__

MappingCollection,因此必须至少定义__getitem____iter____len__;此外,大多数__contains__keysitemsvaluesget__eq____ne__ 都是预期的。如果你的自定义类直接继承自collections.abc.Mapping,只需要实现前三个即可。

演示:

>>> from collections.abc import Mapping
>>> class DemoMapping(Mapping):
...     def __init__(self, a=None, b=None, c=None):
...         self.a, self.b, self.c = a, b, c
...     def __len__(self): return 3
...     def __getitem__(self, name): return vars(self)[name]
...     def __iter__(self): return iter('abc')
...
>>> def foo(a, b, c):
...     print(a, b, c)
...
>>> foo(**DemoMapping(42, 'spam', 'eggs'))
42 spam eggs

如果您在调试器下运行它,您会看到 Python 调用 .keys() 方法,该方法返回一个字典视图,然后在迭代视图时委托给自定义类 __iter__ 方法。然后通过一系列__getitem__ 调用检索这些值。因此,对于您的具体情况,缺少的是 .keys() 方法。

另外,请注意 Python 可能会强制要求键是字符串!

>>> class Numeric(Mapping):
...     def __getitem__(self, name): return {1: 42, 7: 'spam', 11: 'eggs'}[name]
...     def __len__(self): return 3
...     def __iter__(self): return iter((1, 7, 11))
...
>>> dict(Numeric())
{1: 42, 7: 'spam', 11: 'eggs'}
>>> def foo(**kwargs): print(kwargs)
...
>>> foo(**Numeric())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() keywords must be strings

【讨论】:

  • @user3666197 标签 wiki 并非旨在分享百科全书式的学术知识。他们在那里分享标签是如何在 SO 上使用的,并作为进一步信息的指针。请把像你这样的编辑放到维基百科上。
  • @user3666197 另见meta.stackoverflow.com/questions/360170/…,社区成员对您的编辑提出了问题。
【解决方案2】:

Emulating container types

第一组方法用于[...]模拟映射...

还建议映射提供方法keys()values()items()get()clear()setdefault()pop()popitem()copy()和@ 987654331@ 的行为类似于 Python 的标准字典对象。

建议 [...] 映射 [...] 实现 __contains__() 方法以允许有效使用 in 运算符...

进一步建议 [...] 映射 [...] 实现 __iter__() 方法以允许通过容器进行高效迭代

【讨论】:

  • 其中许多仅用于可变映射; 调用不需要改变映射。
  • “第一组方法”指的是哪些方法??
  • 链接到的文档中的那些。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
相关资源
最近更新 更多