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
的行为,即使Foo
是Bar
的基类,它也是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>
正如你所看到的,即使t1
和t2
在内存中的值不同, t1
和t2
也会在内存中输出相同的值。 这就是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
是最通用的,除非你知道事实实例存在。