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
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
这是一个老问题,但似乎没有一个答案提到这一点。在一般情况下,新样式类可能具有不同的值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 提供的原始描述符,它读取内部类型字段。它不是读取该内部类型字段,而是返回一个硬编码的值。
旧式类是问题所在,叹息:
>>> class old: pass
...
>>> x=old()
>>> type(x)
<type 'instance'>
>>> x.__class__
<class __main__.old at 0x6a150>
>>>
在 Python 3 中不是问题,因为现在所有类都是新样式的;-)。
在 Python 2 中,只有从另一个新样式类(包括object
各种内置类型,如dict
、list
、set
、 ...)继承或隐式或显式设置__metaclass__
为type
.
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