我需要测试从文件(和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中所讨论的,如何确定对象是否可迭代?
我找不到映射的任何并行.如在相同的答案上面所讨论的,使用isinstance和collections不是好的解决方案.
因此,在加载像这样的对象时,我必须将我的测试器函数(没有打印)作为我自己的映射测试
try:
tester(**O)
except TypeError:
O = {}
Run Code Online (Sandbox Code Playgroud)
或者python是否有内置的方法来测试这个,就像迭代一样?似乎应该有一个.
编辑
实际上上面的链接答案从未反对isinstance方法,应该更好地阅读它...
使用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)
某些对象可能不是 的实例,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)