Python:可以isinstance(i,type(i))计算为False?

时间:2012-09-13 09:26:41

标签: python oop built-in

我在以下代码中寻找something,以便之后的isinstance()检查在任何情况下都会评估为True

i = WonderfulClass()
classinfo_of_i = something(i)
isinstance(i, classinfo_of_i) # must evaluate to True

如果type是您的答案,如果您解释原因,我将不胜感激。 typeisinstance的真正对应物吗?或者,反过来问,你能想到isinstance(i, type(i))评估为False的情况吗?

这个问题出现在the simple way to check if the elements of a list or set are single type?的上下文中,我们必须经历一个序列并检查所有序列元素是否属于同一类。在这种情况下,元素将相互比较。此比较可以基于type或基于isinstance

关于isinstance(object, classinfo)的相关documentation

  

如果object参数是classinfo的实例,则返回true   参数

4 个答案:

答案 0 :(得分:6)

  

“类型是isinstance的真正对应物吗?或者,反过来问,你能想到isinstance(i,type(i))评估为False的情况吗?”

我看不到isinstance(i, type(i))不会返回True的任何情况。

type()检查并返回实例中的类型对象,因此没有理由为返回的值无法通过isinstance()检查。

深入研究cPython的源代码,我们看到code behind type()只返回附加到实例的类型对象:

v = (PyObject *)o->ob_type;
Py_INCREF(v);
return v;

虽然isintance() code做的第一件事就是检查类型是否完全匹配(后来会继续匹配继承链中的类):

int
PyObject_IsInstance(PyObject *inst, PyObject *cls)
{
   _Py_IDENTIFIER(__instancecheck__);
   PyObject *checker;

   /* Quick test for an exact match */
   if (Py_TYPE(inst) == (PyTypeObject *)cls)
      return 1;

请注意,Py_TYPE只是一个返回obj->ob_type的宏,它与type()的返回值相匹配。这是defined in Include/object.h

#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)

答案 1 :(得分:2)

type()返回预期的内容,但前提是您使用新的样式类(继承自object)。

请考虑以下事项:

>>> class WonderfulClass(object):
...     pass
...
>>> i = WonderfulClass()
>>> isinstance(i,type(i))
True
>>> type(i)
<class '__main__.WonderfulClass'>
>>> class AnotherClass:
...     pass
...
>>> z = AnotherClass()
>>> type(z)
<type 'instance'>
>>> isinstance(z,type(z))
True

因此虽然isinstance检查有效,但值得注意的是差异。

答案 2 :(得分:2)

首先,isinstance旨在处理继承。例如。

>>> isinstance("asdfs", object)
True

这里的字符串被认为是对象的实例,因为“str”类型是“对象”类型的继承人。所以类型不是isinstance的严格对应。

所有东西都是python中的一个对象,因此,isinstance(任何东西,对象)应该为任何东西返回True,因此,数组中的所有值在它们的类层次结构中都有一个共同的祖先:object。

如果您想直接引用更特殊的类型/将其存储在变量中并且能够与其进行比较,types模块可能会对您感兴趣。

答案 3 :(得分:1)

>>> class P:
...   pass
...
>>> p = P()
>>> type(p)
<type 'instance'>
>>> p.__class__
<class __main__.P at 0x015A6A78>

>>> class D(object):
...   pass
...
>>>
>>> d = D()
>>> type(d)
<class '__main__.D'>
>>> d.__class__
<class '__main__.D'>