Pythontypes()或__class__,==或者是

我想testing一个对象是否是一个类的实例,只有这个类(没有子类)。 我可以这样做:

obj.__class__ == Foo obj.__class__ is Foo type(obj) == Foo type(obj) is Foo 

是否有理由相互select? (性能差异,陷阱等)

换句话说:a)使用__class__type(x)有什么实际区别? b)类对象总是安全的比较使用is


更新:感谢所有的反馈。 对于类对象是否是单例,我仍然感到困惑,我的常识说,他们确实很难得到确认(尝试search“python”,“class”,“unique”或“singleton”) 。

我还想澄清一点,就我个人的需要而言,“便宜”的解决scheme是最好的,因为我试图优化几个专门的课程(几乎达到了理智的地步要做的事情是放弃Python,并在C)开发特定的模块。 但是问题背后的原因是要更好地理解语言,因为它的一些特征对于我容易地find这些信息来说有点太模糊了。 这就是为什么我让讨论延伸一点,而不是为了__class__ is的解决,所以我可以听到更有经验的人的意见。 到目前为止,这是非常有成果的!

我进行了一个小testing来衡量4个select的性能。 分析器的结果是:

  Python PyPy (4x) type() is 2.138 2.594 __class__ is 2.185 2.437 type() == 2.213 2.625 __class__ == 2.271 2.453 

不出所料,在所有情况下都比==好。 type()在Python中performance得更好(快2%),而__class__performance更好(快6%)。 有趣的是, __class__ ==在PyPy中比type() is更好。


更新2:很多人似乎不明白我的意思是“一个class级是一个单身人士”,所以我会举一个例子:

 >>> class Foo(object): pass ... >>> X = Foo >>> class Foo(object): pass ... >>> X == Foo False >>> isinstance(X(), Foo) False >>> isinstance(Foo(), X) False >>> x = type('Foo', (object,), dict()) >>> y = type('Foo', (object,), dict()) >>> x == y False >>> isinstance(x(), y) False >>> y = copy.copy(x) >>> x == y True >>> x is y True >>> isinstance(x(), y) True >>> y = copy.deepcopy(x) >>> x == y True >>> x is y True >>> isinstance(x(), y) True 

如果有N个types的对象并没有关系,给定一个对象,只有一个是它的类,因此在这种情况下比较引用是安全的。 由于参考比较总是比价值比较便宜,所以我想知道我的论断是否成立。 我得出的结论是,除非有人提供相反的证据。

对于老式的课程,有一个区别:

 >>> class X: pass ... >>> type(X) <type 'classobj'> >>> X.__class__ Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: class X has no attribute '__class__' >>> x = X() >>> x.__class__ <class __main__.X at 0x171b5d50> >>> type(x) <type 'instance'> 

新式课堂的要点是统一课堂和课堂。 从技术上讲, __class__是唯一可以同时适用于新旧types实例的解决scheme,但也会在旧式类对象本身上引发exception。 你可以在任何对象上调用type() ,但不是每个对象都有__class__ 。 另外,你可以用type()来避免使用__class__

 >>> class Z(object): ... def __getattribute__(self, name): ... return "ham" ... >>> z = Z() >>> z.__class__ 'ham' >>> type(z) <class '__main__.Z'> 

就个人而言,我通常只有一个新风格类的环境,作为一个风格问题,我喜欢使用type()因为我通常更喜欢使用魔法属性的内置函数。 例如,我也喜欢bool(x)x.__nonzero__()

type()的结果等同于新样式类中的obj.__class__ ,而使用is ,use ==来替代类对象并不安全。

对于新的风格类 ,这里最好的方法是type(obj) == Foo

正如Michael Hoffman在他的回答中指出的那样,新旧风格类别之间存在差异,所以对于向后兼容的代码,您可能需要使用obj.__class__ == Foo

对于那些声称isinstance(obj, Foo)更好的情况,请考虑以下情况:

 class Foo(object): pass class Bar(Foo): pass >>> obj = Bar() >>> isinstance(obj, Foo) True >>> type(obj) == Foo False 

OP需要type(obj) == Foo的行为,即使FooBar的基类,它也是false。

is应该只用于身份检查,而不是types检查(有一个例外的规则,你可以和应该使用的is检查单身人士)。

注意:我通常不会使用type==来进行types检查。 types检查的首选方法是isinstance(obj, Foo) 。 如果你有任何理由去检查是不是一个子类的实例,它的味道就像是一个可怕的devise。 当class Foo(Bar): Bar 是一个 Foo ,并且你应该避免任何你的代码的某些部分必须在Foo实例上工作但在Bar实例上中断的情况。

更新:感谢所有的反馈。 对于类对象是否是单例,我仍然感到困惑,我的常识说,他们确实很难得到确认(尝试search“python”,“class”,“unique”或“singleton”) 。

我可以确认__instance__是一个单例。 这是certificate。

 >>> t1=File.test() made class >>> t2=File.test() made class >>> print t1.__class__() made class <File.test object at 0x1101bdd10> >>> print t2.__class__() made class <File.test object at 0x1101bdd10> 

正如你所看到的,即使t1t2在内存中的值不同, t1t2也会在内存中输出相同的值。 这就是certificate。

 >>> print t1 <File.test object at 0x1101bdc90> >>> print t2 <File.test object at 0x1101bdcd0> 

__instance__方法只有在使用class "name"(object):时才存在class "name"(object): 。 如果使用经典样式类class "name":类,则不存在__instance__方法。

这意味着你可能想要使用的type是最通用的,除非你知道事实实例存在。