验证python中的对象是否遵循特定结构

时间:2009-11-03 04:32:16

标签: python

是否有一些简单的方法可以检查某个函数的输入对象是否符合特定结构?例如,我只想要一个字符串键和值为整数列表的字典。

一种方法是编写一个你在对象中传递的递归函数,然后迭代它,在每个级别检查它是你期望的。但我觉得在python中应该有比这更优雅的方法。

4 个答案:

答案 0 :(得分:3)

为什么你会期望Python提供一种“优雅的方式”来检查类型,因为类型检查的整个想法与Pythonic构思世界并与之交互的方式完全不同?通常在Python中你会使用duck typing - 所以“一个整数”也可能同样是一个int,一个long,一个gmpy.mpz - 彼此没有关系的类型,除了它们都实现了相同的核心签名......正如“dict”可能是映射的任何实现,等等。

2.6英寸以后的“抽象基类”概念提供了一种更加系统化的方式来实现和验证鸭子类型,3.0及更高版本的函数注释让您可以与这样的检查系统进行交互(第三-party,因为Python在可预见的未来不采用这样的系统。例如,this recipe提供了一种3.0及以后的方式来执行基于功能注释的“有点但不完全”的类型检查 - 尽管我怀疑它在任何地方都可以达到你想要的深度,但是,它是早期的对于函数注释,我们大多数人都觉得Pythonistas对这种检查的渴望很少,以至于我们不太可能实现这些巨大的系统来代替实际的有用的代码; - )。

答案 1 :(得分:1)

简短回答,不,你必须创建自己的功能。

答案很长:它不是pythonic做你要求的。可能存在一些特殊情况(例如,将字典编组到xmlrpc),但总的来说,假设对象将像他们记录的那样行事。如果他们不这样做,请让AttributeError冒泡。如果您可以使用强制值,则可以使用str()int()进行转换。他们毕竟可以实现__str____add__等使得它们不是int / str的后代,但仍然可用。

def dict_of_string_and_ints(obj):
  assert isinstance(obj, dict)
  for key, value in obj.iteritems(): # py2.4
    assert isinstance(key, basestring)
    assert isinstance(value, list)
    assert sum(isinstance(x, int) for x in value) == len(list)

答案 2 :(得分:0)

由于Python强调只是工作的东西,所以最好的办法是随时随地assert并相信图书馆的用户可以提供适当的数据。如果必须的话,让异常发生;这是因为你的客户没有阅读你的文档字符串。

在你的情况下,像这样:

def myfunction(arrrrrgs):
    assert issubclass(dict, type(arrrrrgs)), "Need a dictionary!"
    for key in arrrrrgs:
        assert type(key) is str, "Need a string!"
        val = arrrrrgs[key]
        assert type(val) is list, "Need a list!"

等等。

真的,这不值得付出努力,如果你在文档字符串中清楚地表达自己,或者抛出适当的例外来指导深夜的调试器,那么让你的程序爆炸。

答案 3 :(得分:0)

我会拍摄并提出一个帮助函数,可以用更通用+更优雅的方式为你做这样的事情:

def check_type(value, type_def):
    """
    This validates an object instanct <value> against a type template <type_def>
    presented as a simplified object.
    E.g.
    if value is list of dictionaries that have string values as key and integers 
    as values:
    >> check_type(value, [{'':0}])
    if value is list of dictionaries, no restriction on key/values
    >> check_type(value, [{}])
    """
    if type(value) != type(type_def):
        return False
    if hasattr(value, '__iter__'):
        if len(type_def) == 0:
            return True
        type_def_val = iter(type_def).next()
        for key in value:
            if not check_type(key, type_def_val):
                return False
        if type(value) is dict:
            if not check_type(value.values(), type_def.values()):
                return False
    return True

评论解释了一个使用样本,但你总是可以深入,例如。

>>> check_type({1:['a', 'b'], 2:['c', 'd']}, {0:['']})
True
>>> check_type({1:['a', 'b'], 2:['c', 3]}, {0:['']})
False

P.S。如果您想要逐个元组验证(例如针对([],'',{0:0}的验证),并且现在无法按预期处理,请随意修改它。