如何在Python中比较两个类/类型?

14 投票
4 回答
39681 浏览
提问于 2025-04-18 02:20

我在一个叫做 classes.py 的模块里定义了两个类:

class ClassA(object):
    pass

class ClassB(object):
    pass

然后在另一个模块里,我正在获取这个模块的属性:

import classes

Class1 = getattr(classes, 'ClassA')
Class2 = getattr(classes, 'ClassA')
print type(Class1) == type(Class2)

Class3 = getattr(classes, 'ClassA')
Class4 = getattr(classes, 'ClassB')
print type(Class3) == type(Class4)

我发现这两种类型的比较都返回了 True,这不是我预期的结果。

我该如何使用 Python 自带的类型值来比较类的类型呢?

4 个回答

1

除了其他回答之外:

Python中有一个叫做元类的概念,简单来说就是“类的类”。这意味着,在Python中,类本身也是一个对象,而且它有自己的类,可以通过内置的 type 函数来访问。

因为 ClassAClassB 默认都是同一个元类的实例,所以它们的比较结果是True。

如果你想了解更多关于元类的内容,可以看看这个StackOverflow的帖子,是个不错的开始。

3

你在比较类对象的类型,这些对象的类型都是 'type'

如果你只是想比较类本身,那就直接比较它们:

print Class3 == Class4
10

如果你想检查两个类型是否相等,那么你应该使用 is 操作符

举个例子:我们可以创建一个简单的元类

class StupidMetaClass(type):
    def __eq__(self, other):
        return False

然后基于这个元类创建一个类:

  • 在 Python 2 中

      class StupidClass(object):
          __metaclass__ = StupidMetaClass
    
  • 在 Python 3 中

    class StupidClass(metaclass=StupidMetaClass):
         pass
    
    

接下来做一个简单的检查

>>> StupidClass == StupidClass

结果是 False,而

>>> StupidClass is StupidClass

则返回预期的 True 值。

所以我们可以看到,== 操作符在类上是可以被重载的,但没有简单的方法可以改变 is 操作符的行为。

18

解释

这就是为什么你的比较没有按预期工作的原因

>>> class ClassA(object):
...     pass
... 
>>> class ClassB(object):
...     pass
... 
>>> type(ClassB)
<class 'type'> 
>>> type(ClassA)
<class 'type'> 
>>> type(ClassA) == type(ClassB)
True

但是为什么 ClassAClassB 会有相同的类型 type 呢?引用一下文档

默认情况下,类是通过 type() 创建的。类的主体在一个新的命名空间中执行,类名被局部绑定到 type(name, bases, namespace) 的结果上。

举个例子:

>>> ClassB
<class '__main__.ClassB'>
>>> type('ClassB', (), {})
<class '__main__.ClassB'>
>>> type(ClassB)
<class 'type'>
>>> type(type('ClassB', (), {}))
<class 'type'>

获取 ClassB 的类型和获取 type('ClassB', (), {}) 的类型是完全一样的,结果都是 type

解决方案

直接比较它们(不使用 type() 函数):

>>> ClassA
<class '__main__.ClassA'>
>>> ClassB
<class '__main__.ClassB'>
>>> ClassA == ClassB
False

或者初始化它们,然后比较它们对象的类型:

>>> a = ClassA()
>>> b = ClassB()
>>> type(a) 
<class '__main__.ClassA'>
>>> type(b) 
<class '__main__.ClassB'>
>>> type(a) == type(b)
False

顺便说一下,你也可以在类的比较中用 is 替代 ==

撰写回答