关于python:什么时候类型(实例)不是实例呢?

When is type(instance) not instance.__class__?

python有内置的函数type,每个实例也有一个__class__属性。我一般认为他们还了同样的东西。即使这两个文件听起来都很相似:

instance.__class__

The class to which a class instance belongs.

type(object)

With one argument, return the type of an object.

但是,在abc.ABCMeta.__instancecheck__中,有一个检查它们是否相同(略短):

1
2
3
subclass = instance.__class__
subtype = type(instance)
if subtype is subclass:

什么时候不是这样?何时type(instance)instance.__class__不同?


type(instance)instance.__class__可能不同,即使是新类型的类,正如pep 3119中提到的guido:

Also, isinstance(x, B) is equivalent to issubclass(x.__class__, B) or issubclass(type(x), B). (It is possible type(x) and x.__class__ are not the same object, e.g. when x is a proxy object.)

例如:

1
2
3
4
5
6
7
8
9
class A:
    pass

class B:
    __class__ = A

b = B()
print(type(b))      # prints <class '__main__.B'>
print(b.__class__)  # prints <class '__main__.A'>

这是旧样式对象(从无继承)的情况。这些对象不具有__class__属性。我认为他们这样做是为了防止错误。Python 2.7示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class A:
    pass

class B(object):
    pass

a = A()
b = B()

print(dir(a)) # ['__doc__', '__module__']
print(dir(b)) # ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

print(b.__class__) # <class '__main__.B'>
print(type(b))     # <class '__main__.B'>

#####################
# The intersting part
print(a.__class__) # __main__.A
print(type(a))     # <type 'instance'>


print(B.__class__) # <type 'type'>
print(type(B))     # <type 'type'>

print(type(A))      # <type 'classobj'>
#print(A.__class__) # AttributeError: class A has no attribute '__class__'

更多信息请参见:

  • python type()或uu class_uuuu,==或is
  • 新类VsClassicClass
  • 为什么'type(myfield)`返回``而不是``?

注意:来自cpython的给定行在2008年最后一次被更改(commit),所以它实际上似乎是一个兼容性的东西,或者他们只是忘记了它。