如何测试对象是否为映射(支持**O用法)

dei*_*aur 5 python mapping

我需要测试从文件(和evaled)读入的对象ConfigParser是否为映射.

这里的术语不完全确定,但让我解释一下.鉴于我的对象被调用,O它必须支持以下列方式使用:

def tester(**kwargs):
     print kwargs

tester(**O)
Run Code Online (Sandbox Code Playgroud)

如果O不支持**,则会导致TypeError,例如TypeError: test() argument after ** must be a mapping, not tuple.

这是一个非常简单的场景,但我需要知道O在使用之前它会工作,我需要绝对肯定它不会失败.如果我测试O的是可迭代的,我会使用类似的东西:

try:
   iter(O)
except:
   O = tuple()
Run Code Online (Sandbox Code Playgroud)

正如In Python中所讨论的,如何确定对象是否可迭代?

我找不到映射的任何并行.如在相同的答案上面所讨论的,使用isinstancecollections不是好的解决方案.

因此,在加载像这样的对象时,我必须将我的测试器函数(没有打印)作为我自己的映射测试

try:
    tester(**O)
except TypeError:
    O = {}
Run Code Online (Sandbox Code Playgroud)

或者python是否有内置的方法来测试这个,就像迭代一样?似乎应该有一个.

编辑

实际上上面的链接答案从未反对isinstance方法,应该更好地阅读它...

Mar*_*ers 9

使用collections.MappingABC:

from collections import Mapping

if isinstance(O, Mapping):
    # O is a mapping
Run Code Online (Sandbox Code Playgroud)

这支持任何实现正确方法的对象被视为映射,包括dict.

演示:

>>> from collections import Mapping
>>> isinstance({}, Mapping)
True
>>> isinstance((), Mapping)
False
Run Code Online (Sandbox Code Playgroud)

  • @deinonychusaur:不,`Mapping` 是一个 ABC,一个抽象基类,任何支持 *methods* 的对象都被视为一个实例。它实际上并不需要从`Mapping` 继承,实现功能就足够了。 (3认同)

unu*_*tbu 6

某些对象可能不是 的实例,collections.Mapping但可以使用双星语法 ( **)解包:

import collections
def tester(**kwargs):
     print kwargs

class D:
    "http://stackoverflow.com/a/8601389/190597 (Raymond Hettinger)"
    def keys(self):
        return ['a', 'b']
    def __getitem__(self, key):
        return key.upper()

obj = D()
tester(**obj)
# {'a': 'A', 'b': 'B'}

print(isinstance(obj, collections.Mapping))
# False
Run Code Online (Sandbox Code Playgroud)

obj必须提供的最小接口是keys__getitem__

print(all(hasattr(obj, attr) for attr in ('keys', '__getitem__')))
# True
Run Code Online (Sandbox Code Playgroud)

  • 不,我是说当 `all(hasattr(obj, attr) for attr in ('keys', '__getitem__'))` 为 `True` 时,`tester(**obj)` 起作用。 (2认同)