本文介绍了类对象是单例吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我们有x = type(a)x == y,是否必然暗示x is y?

If we have x = type(a) and x == y, does it necessarily imply that x is y?

这是一个反例,但这是一个作弊:

Here is a counter-example, but it's a cheat:

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

我无法创建这样的反例:

And I could not create a counterexample like this:

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

为了澄清我的问题-在没有超越相等性的情况下运算符会疯狂地做某件事,一个类是否有可能存在于两个不同的内存位置,或者导入系统会以某种方式防止这种情况发生?

To clarify my question - without overriding equality operators to do something insane, is it possible for a class to exist at two different memory locations or does the import system somehow prevent this?

如果是这样,我们如何证明这种行为-例如,使用重新加载还是__import__?

If so, how can we demonstrate this behavior - for example, doing weird things with reload or __import__?

如果不是,是否由语言保证或在任何地方都有记录?

If not, is that guaranteed by the language or documented anywhere?

结语:

# thing.py
class A:
    pass

最后,这是为我澄清了真实的行为(并支持了Blckknght答案中的主张)

Finally, this is what clarified the real behaviour for me (and it's supporting the claims in Blckknght answer)

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

因此,尽管使用 importlib.reload 可以通过类标识破坏类型检查,无论如何它也将破坏isinstance.

推荐答案

否,除了弄乱元类__eq__方法之外,没有办法创建两个比较起来却不相同的类对象.

No, there's no way to create two class objects that compare equal without being identical, except by messing around with metaclass __eq__ methods.

这种行为虽然不是类所独有的.对于在其类中未定义__eq__方法的任何对象,这都是默认行为.该行为是从object继承的,而object是所有其他(新样式)类的基类.

This behavior though is not something unique to classes. It's the default behavior for any object without an __eq__ method defined in its class. The behavior is inherited from object, which is the base class for all other (new-style) classes. It's only overridden for builtin types that have some other semantic for equality (e.g. container types which compare their contents) and for custom classes that define an __eq__ operator of their own.

关于在不同的内存位置对同一个类获得两个不同的引用,由于Python的对象语义,这实际上是不可能的.对象的内存位置是其身份(至少在cpython中).内容相同的另一个类可以存在于其他地方,但是像您的A1A2示例一样,所有Python逻辑都将其视为不同的对象.

As for getting two different refernces to the same class at different memory locations, that's not really possible due to Python's object semantics. The memory location of the object is its identity (in cpython at least). Another class with identical contents can exist somewhere else, but like in your A1 and A2 example, it's going to be seen as a different object by all Python logic.

这篇关于类对象是单例吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 07:27