type(obj)和obj .__ class__之间的区别

时间:2009-06-29 20:55:52

标签: python new-style-class

type(obj)obj.__class__之间有什么区别?是否有可能type(obj) is not obj.__class__

我想编写一个在提供的对象上一般工作的函数,使用与另一个参数相同类型的默认值1。下面的#1或#2哪个变体会做正确的事情?

def f(a, b=None):
  if b is None:
    b = type(a)(1) # #1
    b = a.__class__(1) # #2

3 个答案:

答案 0 :(得分:36)

这是一个老问题,但没有一个答案似乎提到这一点。在一般情况下, IS 可能使新式类具有type(instance)instance.__class__的不同值:

class ClassA(object):
    def display(self):
        print("ClassA")

class ClassB(object):
    __class__ = ClassA

    def display(self):
        print("ClassB")

instance = ClassB()

print(type(instance))
print(instance.__class__)
instance.display()

输出:

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

原因是ClassB覆盖了__class__描述符,但是对象中的内部类型字段没有改变。 type(instance)直接从该类型字段读取,因此它返回正确的值,而instance.__class__引用新的描述符替换Python提供的原始描述符,后者读取内部类型字段。它不是读取内部类型字段,而是返回硬编码值。

答案 1 :(得分:30)

老式的课是问题,感叹:

>>> class old: pass
... 
>>> x=old()
>>> type(x)
<type 'instance'>
>>> x.__class__
<class __main__.old at 0x6a150>
>>> 

Python 3中没有问题,因为现在所有的类都是新式的; - )。

在Python 2中,只有当一个类继承自另一个新式类(包括object)和各种内置类型(如dictlist时,它才是新式的。 ,set,...)或隐式或明确地将__metaclass__设置为type

答案 2 :(得分:13)

对于旧样式类,

type(obj)type.__class__的行为不相同:

>>> class a(object):
...     pass
...
>>> class b(a):
...     pass
...
>>> class c:
...     pass
...
>>> ai=a()
>>> bi=b()
>>> ci=c()
>>> type(ai) is ai.__class__
True
>>> type(bi) is bi.__class__
True
>>> type(ci) is ci.__class__
False