2014-02-19 68 views
4

我需要测试从ConfigParser文件(和evaled)读入的对象是映射。如何测试对象是否是映射(支持** O用法)

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

def tester(**kwargs): 
    print kwargs 

tester(**O) 

如果O不支持**这将导致类型错误,例如TypeError: test() argument after ** must be a mapping, not tuple

这是一个非常简单的情况,但我需要知道O将在使用它之前工作,我需要绝对肯定它不会失败。如果我曾是一个迭代测试O,我会使用类似:

try: 
    iter(O) 
except: 
    O = tuple() 

正如In Python, how do I determine if an object is iterable?

讨论我无法找到任何并行的映射。正如在上面相同的答案中所讨论的,使用isinstancecollections并不是一个好的解决方案。

所以我必须加载对象,如

try: 
    tester(**O) 
except TypeError: 
    O = {} 

时,使我的测试功能以上(不含印刷),因为我自己的映射检验或不蟒蛇有内建的方式来测试这个像有迭代?看来应该有一个。

编辑

实际上链接的答案上面从来没有反对isinstance方法说话的时候,应该已经阅读它,还应该

回答

6

使用collections.Mapping ABC:

from collections import Mapping 

if isinstance(O, Mapping): 
    # O is a mapping 

这支持任何实施方法的对象被视为映射,其中包括dict

演示:

>>> from collections import Mapping 
>>> isinstance({}, Mapping) 
True 
>>> isinstance((), Mapping) 
False 
+0

但是它必须来自映射或者是映射的东西,这与支持**真的是一回事吗? – deinonychusaur

+0

@deinonychusaur:不,映射是ABC,抽象基类,任何支持*方法*的对象都被认为是一个实例。它实际上并不需要从'Mapping'继承,实现这个功能就足够了。 –

+0

好的感谢您的快速回复,我似乎只是感到困惑,但python映射概念似乎并不如此存在,因此希望它也能帮助其他人。 – deinonychusaur

2

某些对象可能不是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 

obj必须提供最小接口keys__getitem__

print(all(hasattr(obj, attr) for attr in ('keys', '__getitem__'))) 
# True 
+0

所以你说的是,唯一真正的知道方式是测试,或者可能使用'dir'(尽管这会降低信心度)? – deinonychusaur

+1

不,我在说'当'('keys','__getitem __'))'的all(hasattr(obj,attr))是'True',那么'tester(** obj)'工作。 – unutbu

相关问题