如何检查列表中包含的类型?

How to check the types contained in a list?

提问人:user1358 提问时间:1/6/2013 最后编辑:user1358 更新时间:11/17/2015 访问量:3792

问:

我想在不定义函数的情况下执行以下操作:

if isinstance(x,(list,tuple)) and every_element_isinstance(x,basestring):
   foobar

结婚implementing type checking

有速记/吗?builtin

python 错误报告

评论

0赞 Ned Batchelder 1/6/2013
你为什么不想定义一个函数?

答:

5赞 BrtH 1/6/2013 #1
if isinstance(x, (list, tuple)) and all([isinstance(i, basestring) for i in x]):
    foobar

令人惊讶的是,有列表的列表理解比没有列表的列表理解更快,无论是短列表还是长列表:[ ... ]

入围名单:

>>> timeit('isinstance(x, (list, tuple)) and all(isinstance(i, basestring) for i in x)', "x=['a','b','c']")
2.7594685942680144
>>> timeit('isinstance(x, (list, tuple)) and all(isinstance(i, basestring) for i in x)', "x=['a','b','c']")
2.8013695153947538
>>> timeit('isinstance(x, (list, tuple)) and all([isinstance(i, basestring) for i in x])', "x=['a','b','c']")
2.4351678506033068
>>> timeit('isinstance(x, (list, tuple)) and all([isinstance(i, basestring) for i in x])', "x=['a','b','c']")
2.4491469896721583

长名单:

>>> timeit('isinstance(x, (list, tuple)) and all(isinstance(i, basestring) for i in x)', "x=['a','b','c'] * 1000", number=1000)
1.3357901657891489
>>> timeit('isinstance(x, (list, tuple)) and all(isinstance(i, basestring) for i in x)', "x=['a','b','c'] * 1000", number=1000)
1.3305278872818462
>>> timeit('isinstance(x, (list, tuple)) and all([isinstance(i, basestring) for i in x])', "x=['a','b','c'] * 1000", number=1000)
1.2626525921055531
>>> timeit('isinstance(x, (list, tuple)) and all([isinstance(i, basestring) for i in x])', "x=['a','b','c'] * 1000", number=1000)
1.2881240045551863

评论

0赞 BrtH 1/6/2013
@Volatility我提交答案后一秒钟,我就看到了你的弹出窗口。我想,伟大的思想是一样的:D
0赞 user1358 1/6/2013
那我应该选择哪一个呢?我的意思是两者都是完美的
0赞 user1358 1/6/2013
好吧,Volatility 的名声不太好,所以......,对不起 BrtH
0赞 Volatility 1/6/2013
哈哈,谢谢,我正要说我的解决方案更好,因为它少了两个字符:P
0赞 user1358 1/6/2013
实际上我应该选择 BrtH,因为 Volatility 有一个错别字
9赞 Volatility 1/6/2013 #2

我认为这是最好的解决方案(如果我理解这个问题)

if isinstance(x, (list, tuple)) and all(isinstance(i, basestring) for i in x):
    #do whatever

评论

3赞 hynekcer 1/6/2013
这种没有任何列表理解的解决方案对于慢速条件来说更好,因为即使第一个条件不满足,列表理解也会评估所有条件。([... for ...])
0赞 Eric 1/6/2013
isinstance(x, collections.Iterable)这里可能更合适
5赞 miku 1/6/2013 #3

没有内置的来定义泛型类型。但是有很多验证库可以模仿此功能。

使用 https://github.com/alecthomas/voluptuous 的示例:

>>> from voluptuous import Schema
>>> s_list = Schema([basestring]) # only strings in a list are allowed
>>> s_list("hello") 
...
voluptuous.InvalidList: expected a list
>>> s_list([123])
...
voluptuous.InvalidList: invalid list value @ data[0]
>>> s_list(["correct"])
["correct"] # returns the object, if validation was successful

几天前,这个库添加了对元组的支持

>>> s_tuple = voluptuous.Schema((basestring, ))

现在将两者结合起来得到你的结果:

>>> from voluptuous import any

# - this is now equivalent to your code
# - raises Exceptions on invalid input
>>> schema = Schema(any(s_list, s_tuple))

它甚至比双倍的速度略快:isinstance

>>> from timeit import timeit

>>> timeit('(schema(i) for i in x)', "x=['a','b','c']")
0.679318904876709

>>> timeit("""
        (isinstance(x, (list, tuple)) 
         and all(isinstance(i, basestring)) for i in x)""", "x=['a','b','c']")
0.7801780700683594
0赞 Jakub 11/17/2015 #4

使用妖娆的“0.8.7”,您可以从 miku 更新答案并跳过“元组部分”:

>>> from voluptuous import Schema
>>> from timeit import timeit
>>> s_list = Schema([basestring]) # only strings in a list are allowed
>>> timeit('(s_list(i) for i in x)', "x=['a','b','c']")
0.503572940826416
>>> timeit("(isinstance(x, (list, tuple)) and all(isinstance(i, basestring)) for i in x)", "x=['a','b','c']")
0.5400209426879883