检查一个对象是否为列表的Pythonic方式是什么?
我有一个函数,它可以接收一个数字或者一组数字。我想知道用什么方法检查它到底是哪种情况最符合Python的风格。到目前为止,我想到的是用try/except块来检查是否可以切片第一个元素,比如说用obj[0:0]。
编辑:
我好像因为没有提供足够的信息而引发了一场争论。为了完整起见,我来补充一些细节,这样我可以选择最适合我情况的答案:
我在使用Python 2.6运行Django,我正在写一个函数,这个函数可能接收一个Django模型实例或者一个查询集对象,并对其进行操作。其中一个操作涉及使用'filter in',这需要一个列表(也就是查询集输入),如果不是列表的话,我就会使用'get'过滤器(Django的get过滤器)。
7 个回答
11
你不需要这样做。
这个方法只适用于Python 2.6及以上版本。如果你使用的是更低版本,可以参考Alex的解决方案。
Python支持一种叫做鸭子类型的概念。你可以通过ABC类来检查某些功能。
import collections
def mymethod(myvar):
# collections.Sqeuence to check for list capabilities
# collections.Iterable to check for iterator capabilities
if not isinstance(myvar, collections.Iterable):
raise TypeError()
13
if isinstance(your_object, list):
print("your object is a list!")
这比用类型检查要更符合Python的风格。
看起来也更快:
>>> timeit('isinstance(x, list)', 'x = [1, 2, 3, 4]')
0.40161490440368652
>>> timeit('type(x) is list', 'x = [1, 2, 3, 4]')
0.46065497398376465
>>>
21
在这种情况下,你通常需要检查任何可迭代的对象,而不仅仅是列表。如果你接受列表或数字,拒绝(例如)元组就显得很奇怪。你可能想把字符串当作“标量”来处理。在Python 2.*中,这意味着 str
或 unicode
。所以,你可以选择:
def isNonStringIterable(x):
if isinstance(x, basestring):
return False
try: iter(x)
except: return False
else: return True
或者,通常更方便的是:
def makeNonStringIterable(x):
if isinstance(x, basestring):
return (x,)
try: return iter(x)
except: return (x,)
在这里,你只需要写 for i in makeNonStringIterable(x): ...