确定一个对象的types?

有一个简单的方法来确定一个variables是一个列表,字典,或其他? 我得到一个可能是任何types的对象,我需要能够区分。

要获取对象的types,可以使用内置的type()函数。 传递一个对象作为唯一的参数将返回该对象的types对象:

 >>> type([]) is list True >>> type({}) is dict True >>> type('') is str True >>> type(0) is int True >>> type({}) <type 'dict'> >>> type([]) <type 'list'> 

这当然也适用于自定义types:

 >>> class Test1 (object): pass >>> class Test2 (Test1): pass >>> a = Test1() >>> b = Test2() >>> type(a) is Test1 True >>> type(b) is Test2 True 

注意type()只会返回对象的直接types,但是不能告诉你typesinheritance。

 >>> type(b) is Test1 False 

为了解决这个问题,你应该使用isinstance函数。 这当然也适用于内置的types:

 >>> isinstance(b, Test1) True >>> isinstance(b, Test2) True >>> isinstance(a, Test1) True >>> isinstance(a, Test2) False >>> isinstance([], list) True >>> isinstance({}, dict) True 

isinstance()通常是确保对象types的首选方法,因为它也会接受派生types。 所以,除非实际需要types对象(无论出于何种原因),否则使用isinstance()优于type()

isinstance()的第二个参数也接受一个types的元组,所以可以一次检查多个types。 isinstance将返回true,如果该对象是以下任何types的:

 >>> isinstance([], (tuple, list, set)) True 

你可以使用type()来做到这一点:

 >>> a = [] >>> type(a) <type 'list'> >>> f = () >>> type(f) <type 'tuple'> 

使用tryexcept块可能会更加Pythonic。 那样的话,如果你有一个像名单那样庸医的类,或者像一个字典那样的庸医,那么它将会正确地行事,而不pipe它的types是什么。

为了澄清,variablestypes之间的“区别”的首选方法是使用鸭型打字 :只要variables响应的方法(和返回types)是你的子程序所期望的,就像你期待的那样对待它成为。 例如,如果您有一个用getattrsetattr重载括号运算符的类,但是使用了一些有趣的内部scheme,那么如果它正在尝试模拟它,那么将它作为一个字典是合适的。

type(A) is type(B)的另一个问题type(A) is type(B)检查是,如果AB的子类,那么当以编程的方式计算它的值时,它的计算结果为false 。 如果一个对象是一个列表的子类,它应该像列表一样工作:检查另一个答案中提供的types将防止这种情况。 (但isinstance将工作)。

在对象的实例上,你也有:

 __class__ 

属性。 这里是一个从Python 3.3控制台取得的示例

 >>> str = "str" >>> str.__class__ <class 'str'> >>> i = 2 >>> i.__class__ <class 'int'> >>> class Test(): ... pass ... >>> a = Test() >>> a.__class__ <class '__main__.Test'> 

请注意,在python 3.x和新风格的类(可selectPython 2.6)类和types已合并,这有时会导致意想不到的结果。 主要是因为这个原因,我最喜欢的testingtypes/类的方式是isinstance内置函数。

确定一个Python对象的types

确定types的对象的type

 >>> obj = object() >>> type(obj) <class 'object'> 

尽pipe它起作用了,但避免使用__class__这样的双下划线属性 – 它们在语义上不是公共的,而且在这种情况下可能不是这样,内置函数通常具有更好的行为。

 >>> obj.__class__ # avoid this! <class 'object'> 

types检查

有一个简单的方法来确定一个variables是一个列表,字典,或其他? 我得到一个可能是任何types的对象,我需要能够区分。

那么这是一个不同的问题,不要使用type – use isinstance

 def foo(obj): """given a string with items separated by spaces, or a list or tuple, do something sensible """ if isinstance(obj, str): obj = str.split() return _foo_handles_only_lists_or_tuples(obj) 

这涵盖了你的用户可能通过inheritancestr来做一些聪明或者合理的事情 – 根据Liskov Substitution的原则,你希望能够在不破坏代码的情况下使用子类实例,并且支持这一点。

使用抽象

更好的是,您可以从collectionsnumbers查找特定的抽象基类:

 from collections import Iterable from numbers import Number def bar(obj): """does something sensible with an iterable of numbers, or just one number """ if isinstance(obj, Number): # make it a 1-tuple obj = (obj,) if not isinstance(obj, Iterable): raise TypeError('obj must be either a number or iterable of numbers') return _bar_sensible_with_iterable(obj) 

或者只是不明确地键入检查

或者,也许最重要的是,使用鸭子打字,而不是明确的types检查你的代码。 鸭子打字支持Liskovreplace更加优雅和较不详细。

 def baz(obj): """given an obj, a dict (or anything with an .items method) do something sensible with each key-value pair """ for key, value in obj.items(): _baz_something_sensible(key, value) 

结论

  • 使用type来实际得到一个实例的类。
  • 使用isinstance显式检查实际的子类或注册的抽象。
  • 只要避免types检查在哪里是有道理的。

您可以使用type()isinstance()

 >>> type([]) is list True 

被警告你可以通过在同名的当前范围中分配一个variables来打开list或任何其他types。

 >>> the_d = {} >>> t = lambda x: "aight" if type(x) is dict else "NOPE" >>> t(the_d) 'aight' >>> dict = "dude." >>> t(the_d) 'NOPE' 

上面我们看到dict被重新分配给一个string,因此testing:

 type({}) is dict 

…失败。

为了解决这个问题,更谨慎地使用type()

 >>> import __builtin__ >>> the_d = {} >>> type({}) is dict True >>> dict ="" >>> type({}) is dict False >>> type({}) is __builtin__.dict True 

虽然问题是相当老的,但是我偶然发现了一个正确的方法,我认为它仍然需要澄清, 至less对于Python 2.x (没有检查Python 3,但是由于经典类出现问题这些版本都没有了,可能没关系)。

在这里,我试图回答标题的问题: 我如何确定任意对象的types ? 关于使用或不使用isinstance的其他build议很多评论和答案,但我没有解决这些问题。

type()方法的主要问题是它不适用于旧样式的实例

 class One: pass class Two: pass o = One() t = Two() o_type = type(o) t_type = type(t) print "Are o and t instances of the same class?", o_type is t_type 

执行这段代码会产生:

 Are o and t instances of the same class? True 

我认为,这不是大多数人所期望的。

__class__方法是最接近正确的方法,但在一个关键的情况下不起作用:当传入的对象是旧式 (不是实例!)时,因为这些对象缺less这种属性。

这是我能想到的最小的代码片段,以一致的方式满足这样一个合法的问题:

 #!/usr/bin/env python from types import ClassType #we adopt the null object pattern in the (unlikely) case #that __class__ is None for some strange reason _NO_CLASS=object() def get_object_type(obj): obj_type = getattr(obj, "__class__", _NO_CLASS) if obj_type is not _NO_CLASS: return obj_type # AFAIK the only situation where this happens is an old-style class obj_type = type(obj) if obj_type is not ClassType: raise ValueError("Could not determine object '{}' type.".format(obj_type)) return obj_type 

除了之前的答案之外,值得一提的是collections.abc的存在,其中包含几个抽象基类(ABCs),它们可以补充鸭子的input。

例如,而不是显式检查是否有列表:

 isinstance(my_obj, list) 

你可以,如果你只想看看你有没有允许获取项目的对象,使用collections.abc.Sequence

 from collections.abc import Sequence isinstance(my_obj, Sequence) 

如果您对允许获取,设置删除项目(即可序列)的对象严格感兴趣,则可以selectcollections.abc.MutableSequence

在那里定义了许多其他的ABC, Mapping可以用作映射, IterableCallable等的对象。 所有这些的完整列表可以在collections.abc的文档中看到。

小心使用isinstance

 isinstance(True, bool) True >>> isinstance(True, int) True 

但types

 type(True) == bool True >>> type(True) == int False