MSe*_*ert 9 python types python-3.x
Python具有内置函数type,每个实例也有一个__class__属性.我一般认为他们回归了同样的事情.甚至两个声音的文档都相似:
instance.__class__类实例所属的类.
和
type(object)使用一个参数,返回对象的类型.
但是,abc.ABCMeta.__instancecheck__检查它们是否相同(略微缩短):
subclass = instance.__class__
subtype = type(instance)
if subtype is subclass:
什么时候不是这样的?什么时候type(instance)不一样instance.__class__?
type(instance)即使是新式的类,也instance.__class__可能会有所不同,正如 Guido van Rossum 在PEP 3119中提到的那样:
另外,
isinstance(x, B)相当于issubclass(x.__class__, B) or issubclass(type(x), B). (有可能type(x)和x.__class__不是同一个对象,例如何时x是代理对象。)
例如,weakref.proxy标准库的函数创建代理对象。
>>> import weakref
>>> class A: pass
... 
>>> a = A()
>>> type(weakref.proxy(a))
<class 'weakproxy'>
>>> weakref.proxy(a).__class__
<class '__main__.A'>
>>> repr(weakref.proxy(a))
'<weakproxy at 0x10065ab30 to A at 0x1006534c0>'
__repr__请注意,代理对象的方法的实现使用type(instance),而不是instance.__class__,因为该方法的主要目的__repr__是在调试时提供足够的信息来重新创建对象。
type(instance)实例的真实类object存储在实例上的槽中__class__ (即,在实例布局中的固定偏移处)。它只能通过数据描述符 vars(object)['__class__'](其方法__get__允许属性检索,其方法__set__允许属性赋值,其方法__delete__禁止属性删除)或等效地通过内置函数type(其单参数形式允许属性检索)来访问:
>>> class A: pass
... 
>>> a = A()
>>> type(a)
<class '__main__.A'>
>>> vars(object)['__class__'].__get__(a)
<class '__main__.A'>
>>> class B: pass
... 
>>> vars(object)['__class__'].__set__(a, B)
>>> type(a)
<class '__main__.B'>
>>> vars(object)['__class__'].__get__(a)
<class '__main__.B'>
>>> vars(object)['__class__'].__delete__(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't delete __class__ attribute
instance.__class__如果数据描述符vars(object)['__class__']没有在object子类中被重写,则通过数据描述instance.__class__符访问真实类:instance
>>> class A: pass
... 
>>> a = A()
>>> type(a)
<class '__main__.A'>
>>> a.__class__
<class '__main__.A'>
>>> class B: pass
... 
>>> a.__class__ = B
>>> type(a)
<class '__main__.B'>
>>> a.__class__
<class '__main__.B'>
>>> del a.__class__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't delete __class__ attribute
但如果数据描述符在子类vars(object)['__class__']中被重写object,instance.__class__则无法访问真正的类instance。此外,如果覆盖不是数据描述符,它本身可以在以下位置被覆盖instance:
>>> class A: __class__ = int  # overrides vars(object)['__class__']
... 
>>> a = A()
>>> type(a)
<class '__main__.A'>
>>> a.__class__
<class 'int'>
>>> a.__class__ = str  # overrides vars(A)['__class__'] (not a data descriptor)
>>> type(a)
<class '__main__.A'>
>>> a.__class__
<class 'str'>
>>> del a.__class__
>>> type(a)
<class '__main__.A'>
>>> a.__class__
<class 'int'>
| 归档时间: | 
 | 
| 查看次数: | 463 次 | 
| 最近记录: |