Python type()或__class__,==或is

发布于 2021-01-29 17:05:48

我想测试一个对象是否是一个类的实例,并且只有这个类(没有子类)。我可以使用以下方法之一:

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

有理由选择一个吗?(性能差异,陷阱等)

换句话说:a)使用__class__和之间有什么实际区别type(x)?b)类对象是否始终可以安全地进行比较is


更新: 谢谢大家的反馈。我仍然对类对象是否是单例感到困惑,我的常识说它们是单例,但是确实很难得到一个确认(尝试搜索“ python”,“
class”和“ unique”或“ singleton”) 。

我还想澄清一下,对于我的特殊需求,最有效的“更便宜”的解决方案是最好的,因为我正在尝试从几个专门的类中最大程度地优化(几乎达到了明智的程度)。要做的是删除Python并在C中开发特定模块)。但问题背后的原因是要更好地理解语言,因为它的某些功能对于我来说很难轻易找到这些信息。这就是为什么我只允许讨论扩展一点,而不是为解决问题而定__class__ is,所以我可以听到更多有经验的人的意见。到目前为止,已经取得了丰硕的成果!

我进行了一个小测试,以比较这四种替代产品的性能。分析器结果为:

               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

毫不奇怪,它的is表现比==所有情况都好。type()在Python中的性能更好(快2%),__class__在PyPy中的性能更好(快6%)。有趣的是,__class__ ==在PyPy中的效果要好于type() is


更新2: 很多人似乎不理解我的意思是“一个类是一个单例”,所以我以一个例子为例:

>>> 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个类型type的对象无关紧要,给定一个对象,它的类将只有一个,因此在这种情况下比较以供参考是安全的。而且由于引用比较总是比值比较便宜,所以我想知道我的上述主张是否成立。我得出的结论是这样做的,除非有人提出相反的证据。

关注者
0
被浏览
49
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    对于老式类,有一个区别:

    >>> 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__是唯一适用于新旧类实例的解决方案,但也会对旧类对象本身抛出异常。您可以调用type()任何对象,但不是每个对象都具有__class__。另外,您可以以__class__一种无法与之混为一谈的方式与之混为一谈type()

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

    就个人而言,我通常只有一个带有新样式类的环境,就样式而言type(),我倾向于使用它,因为当它们存在时,我通常更喜欢内置函数而不是使用魔术属性。举例来说,我也宁愿bool(x)x.__nonzero__()



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看