我需要测试从eval
编辑的文件(和ConfigParser
ed)读入的对象是否为映射。
这里的术语不完全确定,但让我解释一下。鉴于我的对象被称为O
,它必须支持以下列方式使用:
def tester(**kwargs):
print kwargs
tester(**O)
如果O
不支持**,则会导致TypeError,例如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?
中所述我找不到映射的任何并行。正如上面相同的答案中所讨论的,使用isinstance
和collections
并不是一个好的解决方案。
所以在加载像
这样的对象时,我必须将我的测试器功能(没有打印)作为我自己的映射测试try:
tester(**O)
except TypeError:
O = {}
或者python是否有内置的测试方法,就像迭代一样?似乎应该有一个。
修改
实际上上面的链接答案从未对isinstance方法发表过反应,应该更好地阅读...
答案 0 :(得分:8)
使用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
答案 1 :(得分:3)
某些对象可能不是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