gpt4 book ai didi

python - type(instance) 何时不同于 instance.__class__?

转载 作者:太空狗 更新时间:2023-10-29 20:27:06 25 4
gpt4 key购买 nike

Python 有内置函数 type :

class type(object)

With one argument, return the type of an object. The return value is a type object and generally the same object as returned by object.__class__.

Python 也有特殊属性 __class__ :

instance.__class__

The class to which a class instance belongs.

我曾经认为它们指的是同一个对象。然而在方法abc.ABCMeta.__instancecheck__检查它们是否相同:

    def __instancecheck__(cls, instance):
"""Override for isinstance(instance, cls)."""
# Inline the cache checking
subclass = instance.__class__
# […]
subtype = type(instance)
if subtype is subclass:
# […]

什么时候 type(instance) 不同于 instance.__class__

最佳答案

type(instance)instance.__class__ 可能不同,即使是 new-style classes ,正如 Guido van Rossum 在 PEP 3119 中提到的那样:

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

例如,函数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__ 方法的主要目的是提供足够的信息调试时重新创建对象。

类型(实例)

object 实例的真实类存储在实例的 __class__ slot 中(即实例布局中的固定偏移量).它只能通过 data descriptor 访问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

实例.__class__

如果数据描述符 vars(object)['__class__']object 子类中没有被覆盖,instance.__class__ 访问通过数据描述符的实例的真实类:

>>> 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 中被覆盖:

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

关于python - type(instance) 何时不同于 instance.__class__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42384991/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com