classobjects是单身人士吗?

wim*_*wim 12 python identity python-3.x

如果我们拥有x = type(a)并且x == y,它是否一定意味着x is y

这是一个反例,但这是一个骗子:

>>> class BrokenEq(type):
...     def __eq__(cls, other):
...         return True
...     
>>> class A(metaclass=BrokenEq):
...     pass
... 
>>> a = A()
>>> x = type(a)
>>> x == A, x is A
(True, True)
>>> x == BrokenEq, x is BrokenEq
(True, False)
Run Code Online (Sandbox Code Playgroud)

我无法创建这样的反例:

>>> A1 = type('A', (), {})
>>> A2 = type('A', (), {})
>>> a = A1()
>>> x = type(a)
>>> x == A1, x is A1
(True, True)
>>> x == A2, x is A2
(False, False)
Run Code Online (Sandbox Code Playgroud)

为了澄清我的问题 - 没有重写等式运算符来做一些疯狂的事情,一个类是否可能存在于两个不同的内存位置,或者导入系统是否以某种方式阻止了这一点?

如果是这样,我们如何证明这种行为 - 例如,通过重新加载或做什么奇怪的事情__import__

如果没有,是由语言保证还是在任何地方记录?


结语:

# thing.py
class A:
    pass
Run Code Online (Sandbox Code Playgroud)

最后,这是澄清我的真实行为(它支持Blckknght答案中的声明)

>>> import sys
>>> from thing import A
>>> a = A()
>>> isinstance(a, A), type(a) == A, type(a) is A
(True, True, True)
>>> del sys.modules['thing']
>>> from thing import A
>>> isinstance(a, A), type(a) == A, type(a) is A
(False, False, False)
Run Code Online (Sandbox Code Playgroud)

因此,尽管使用的代码importlib.reload可能会破坏类标识的类型检查,但isinstance无论如何它也会破坏.

Blc*_*ght 5

不,没有办法创建两个比较相等而不相同的类对象,除非弄乱了元类__eq__方法.

这种行为虽然不是类的独特之处.对于没有__eq__在其类中定义的方法的任何对象,它是默认行为.行为是继承自的object,它是所有其他(新式)类的基类.它只被覆盖了内置类型,它们具有一些其他相等的语义(例如,比较其内容的容器类型)和定义__eq__自己的运算符的自定义类.

至于在不同的内存位置对同一个类进行两次不同的引用,由于Python的对象语义,这实际上是不可能的.对象的内存位置它的标识(至少在cpython中).与相同内容的另外一类可以存在别的地方,但像你A1A2例子,这将被看作是所有的Python逻辑不同的对象.


use*_*ica 5

我不知道有关==类型如何工作的任何文档,但它肯定是通过身份工作.您可以看到CPython 2.7实现是一个指针比较:

static PyObject*
type_richcompare(PyObject *v, PyObject *w, int op)
{
    ...

    /* Compare addresses */
    vv = (Py_uintptr_t)v;
    ww = (Py_uintptr_t)w;
    switch (op) {
    ...
    case Py_EQ: c = vv == ww; break;
Run Code Online (Sandbox Code Playgroud)

CPython 3.5中,type没有实现自己的tp_richcompare,所以它继承了默认的相等比较object,这是一个指针比较:

PyTypeObject PyType_Type = {
    ...
    0,                                          /* tp_richcompare */
Run Code Online (Sandbox Code Playgroud)