测试变量是列表还是元组

问题:测试变量是列表还是元组

在python中,测试变量是否包含列表或元组的最佳方法是什么?(即集合)

isinstance()邪恶的建议在这里?http://www.canonical.org/~kragen/isinstance/

更新:我想从字符串中区分列表的最常见原因是当我有一些无限深的嵌套树/字符串列表等列表的数据结构时,我正在使用递归算法进行探索,我需要知道我何时击中“叶子”节点。

In python, what’s the best way to test if a variable contains a list or a tuple? (ie. a collection)

Is isinstance() as evil as suggested here? http://www.canonical.org/~kragen/isinstance/

Update: the most common reason I want to distinguish a list from a string is when I have some indefinitely deep nested tree / data-structure of lists of lists of lists of strings etc. which I’m exploring with a recursive algorithm and I need to know when I’ve hit the “leaf” nodes.


回答 0

继续使用,isinstance如果需要的话。这有点邪恶,因为它不包括自定义序列,迭代器和您可能实际需要的其他东西。但是,有时,例如,有人传递字符串时,您需要采取不同的行为。我的偏好是明确检查strunicode类似:

import types
isinstance(var, types.StringTypes)

NB千万不要误会types.StringTypetypes.StringTypes。后者包含strunicode对象。

types许多人认为该模块已过时,只支持直接检查对象的类型,因此,如果您不想使用以上内容,则可以替代地显式检查strand unicode,例如:

isinstance(var, (str, unicode)):

编辑:

更好的是:

isinstance(var, basestring)

结束编辑

在这两种情况中的任何一种之后,您都可以回到正常的序列状态,让非序列引发适当的异常。

看到关于类型检查的“邪恶”之处不是您可能不想对某种特定类型的对象表现出不同的行为,而是您人为地限制了函数使用意外的对象类型来执行正确的操作,否则它们将执行正确的操作。如果您有未经过类型检查的最终后备,则可以删除此限制。应该注意的是,过多的类型检查是一种代码异味,表明您可能想要进行一些重构,但这并不一定意味着您应该避免从getgo中进行此操作。

Go ahead and use isinstance if you need it. It is somewhat evil, as it excludes custom sequences, iterators, and other things that you might actually need. However, sometimes you need to behave differently if someone, for instance, passes a string. My preference there would be to explicitly check for str or unicode like so:

import types
isinstance(var, types.StringTypes)

N.B. Don’t mistake types.StringType for types.StringTypes. The latter incorporates str and unicode objects.

The types module is considered by many to be obsolete in favor of just checking directly against the object’s type, so if you’d rather not use the above, you can alternatively check explicitly against str and unicode, like this:

isinstance(var, (str, unicode)):

Edit:

Better still is:

isinstance(var, basestring)

End edit

After either of these, you can fall back to behaving as if you’re getting a normal sequence, letting non-sequences raise appropriate exceptions.

See the thing that’s “evil” about type checking is not that you might want to behave differently for a certain type of object, it’s that you artificially restrict your function from doing the right thing with unexpected object types that would otherwise do the right thing. If you have a final fallback that is not type-checked, you remove this restriction. It should be noted that too much type checking is a code smell that indicates that you might want to do some refactoring, but that doesn’t necessarily mean you should avoid it from the getgo.


回答 1

if type(x) is list:
    print 'a list'
elif type(x) is tuple:
    print 'a tuple'
else:
    print 'neither a tuple or a list'
if type(x) is list:
    print 'a list'
elif type(x) is tuple:
    print 'a tuple'
else:
    print 'neither a tuple or a list'

回答 2

没有什么错误使用isinstance,只要它不是多余的。如果变量仅应是列表/元组,则记录该接口并按原样使用它。否则,检查是完全合理的:

if isinstance(a, collections.Iterable):
    # use as a container
else:
    # not a container!

这种类型的检查确实有一些很好的使用情况,如与标准字符串startswith / 的endsWith方法(虽然是准确的,这些都是使用一个明确的检查,看它是否是一个元组用C语言实现的CPython的-有不止一种方法如您所链接的文章所述,以解决此问题)。

显式检查通常比尝试将对象用作容器并处理异常要好-这可能会导致部分或不必要地运行代码的各种问题。

There’s nothing wrong with using isinstance as long as it’s not redundant. If a variable should only be a list/tuple then document the interface and just use it as such. Otherwise a check is perfectly reasonable:

if isinstance(a, collections.Iterable):
    # use as a container
else:
    # not a container!

This type of check does have some good use-cases, such as with the standard string startswith / endswith methods (although to be accurate these are implemented in C in CPython using an explicit check to see if it’s a tuple – there’s more than one way to solve this problem, as mentioned in the article you link to).

An explicit check is often better than trying to use the object as a container and handling the exception – that can cause all sorts of problems with code being run partially or unnecessarily.


回答 3

将自变量需要记录为序列,并将其用作序列。不要检查类型。

Document the argument as needing to be a sequence, and use it as a sequence. Don’t check the type.


回答 4

如何:hasattr(a, "__iter__")

它告诉返回的对象是否可以作为生成器进行迭代。默认情况下,元组和列表可以,但字符串类型不能。

How about: hasattr(a, "__iter__") ?

It tells if the object returned can be iterated over as a generator. By default, tuples and lists can, but not the string types.


回答 5

在Python 2.8 type(list) is list返回上,false
我建议以这种可怕的方式比较类型:

if type(a) == type([]) :
  print "variable a is a list"

(至少在我的系统上,在Mac OS X Yosemite上使用anaconda)

On Python 2.8 type(list) is list returns false
I would suggest comparing the type in this horrible way:

if type(a) == type([]) :
  print "variable a is a list"

(well at least on my system, using anaconda on Mac OS X Yosemite)


回答 6

Python使用“鸭子类型”,即,如果变量像鸭子一样醒来,则它一定是鸭子。在您的情况下,您可能希望它是可迭代的,或者您想以某个索引访问该项目。您应该这样做:即在块中for var:或块var[idx]内使用对象try,如果遇到异常,它就不是鸭子。

Python uses “Duck typing”, i.e. if a variable kwaks like a duck, it must be a duck. In your case, you probably want it to be iterable, or you want to access the item at a certain index. You should just do this: i.e. use the object in for var: or var[idx] inside a try block, and if you get an exception it wasn’t a duck…


回答 7

>>> l = []
>>> l.__class__.__name__ in ('list', 'tuple')
True
>>> l = []
>>> l.__class__.__name__ in ('list', 'tuple')
True

回答 8

如果您只需要知道是否可以foo[123]对变量使用符号,则可以使用以下命令检查__getitem__属性的存在(这是python在通过索引访问时调用的内容)hasattr(foo, '__getitem__')

If you just need to know if you can use the foo[123] notation with the variable, you can check for the existence of a __getitem__ attribute (which is what python calls when you access by index) with hasattr(foo, '__getitem__')


回答 9

如果您真的想处理几乎任何函数参数,则必须进行更复杂的测试。

type(a) != type('') and hasattr(a, "__iter__")

尽管通常只需说明一个函数期望可迭代然后仅检查即可type(a) != type('')

也可能会发生这样的情况:对于字符串,您具有简单的处理路径,或者您会变得很好并进行拆分等,因此您不想大喊大叫,如果有人给您发送一些奇怪的东西,请让他拥有一个exceptions。

Has to be more complex test if you really want to handle just about anything as function argument.

type(a) != type('') and hasattr(a, "__iter__")

Although, usually it’s enough to just spell out that a function expects iterable and then check only type(a) != type('').

Also it may happen that for a string you have a simple processing path or you are going to be nice and do a split etc., so you don’t want to yell at strings and if someone sends you something weird, just let him have an exception.


回答 10

找出变量是列表变量还是元组变量或通常检查变量类型的另一种简便方法是:

    def islist(obj):

        if ("list" in str(type(obj)) ): return True

        else : return False

Another easy way to find out if a variable is either list or tuple or generally check variable type would be :

    def islist(obj):

        if ("list" in str(type(obj)) ): return True

        else : return False

回答 11

原则上,我同意上面的Ignacio,但是您也可以使用type来检查某项是元组还是列表。

>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')

In principle, I agree with Ignacio, above, but you can also use type to check if something is a tuple or a list.

>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')