检查一个对象是否为列表的Pythonic方式是什么?

10 投票
7 回答
854 浏览
提问于 2025-04-15 14:32

我有一个函数,它可以接收一个数字或者一组数字。我想知道用什么方法检查它到底是哪种情况最符合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.*中,这意味着 strunicode。所以,你可以选择:

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): ...

撰写回答