如何在python中为嵌套列表和基本类型提供类型检查器?

时间:2015-07-16 15:38:45

标签: python python-2.6

如果我需要为包含嵌套列表的基本类型编写类型验证器,那么标准方法是什么。

即。如果我获得了值a和字符串list<list<int>>,我如何检查a实际上是list list int s?

这是否有Pythonic方法?

注意:我知道Python是关于鸭子打字的,只是在这种情况下我需要进行一些验证,因为数据将传递给另一个系统。

4 个答案:

答案 0 :(得分:1)

我必须承认,这是我第一次在年龄中触及递归,但我认为检查对象的每个项目的唯一方法是通过递归。或动态编程,我不喜欢动态编程:P

我绝对不喜欢解析字符串,所以我选择只传入类型。

def typecheck(obj, *args):
    if isinstance(obj, args[0]):
        if len(args) == 1: # last one to check. Base case.
            return True
        if hasattr(args[0], "__iter__"): 
            #in other words, am I an iterator?
            for i in obj:
                if not typecheck(i, *args[1:]):
                    return False
            return True
     else: 
        return False

In [23]: typecheck([[3,3, "a"]],list, list, int)
Out[23]: False

In [24]: typecheck([[3,3]],list, list, int)
Out[24]: True

向此添加logging应该是非常简单的,因为一个变体只会告诉您对象的错误类型

答案 1 :(得分:0)

您可以使用isinstance检查某些内容的类型

def is_list_of_list_of_int(a):
    return isinstance(a, list) and isinstance(a[0], list) and isinstance(a[0][0], int)

>>> is_list_of_list_of_int([[1,2,3],[2,3,4]])
True
>>> is_list_of_list_of_int(5)
False

另一种方法是“请求宽恕而不是许可”

def get_value_safe(a, i, j):
    try:
        return a[i][j]
    except TypeError:
        print('not a list of list')
        return None

>>> get_value_safe([[1,2,3],[2,3,4]], 1, 2)
4
>>> get_value_safe([1,2,3], 1, 2)
not a list of list

答案 2 :(得分:0)

假设您只想检查列表和基本类型,答案的第一部分是将类型规范解析为类型列表(从父级到子级):

import __builtin__
def parse_spec(str_spec):
    return [getattr(__builtin__, x) for x in str_spec.rstrip('>').split('<')]

第二部分验证指定值是否符合规范:

def validate(value, spec):
    for t in spec:
        if not isinstance(value, t):
            return False
        try:
            value = value[0]
        except TypeError:
            pass
    return True

因此,您可以按如下方式组合这些功能:

>>> validate([10], parse_spec('list<int>'))
True
>>> validate([10], parse_spec('int'))
False
>>> validate([['something']], parse_spec('list<list<str>>'))
True

答案 3 :(得分:0)

如果你想检查所有元素是否具有任意级别的嵌套,我将使用递归:

from collections import Iterable


def is_list_or_int(l):
    if not isinstance(l, (list, int)):
        return False
    if isinstance(l, Iterable):
        for ele in l:
            if not is_list_or_int(ele):
                return False
    return True

输出:

In [9]: is_list_or_int([1, [2, [[["4"], 3, 4]]],2, 3, 4])
Out[9]: False

In [10]: is_list_or_int([1, [2, [[[4], 3, 4]]],2, 3, 4])
Out[10]: True