【问题标题】:What is the purpose of checking self.__class__?检查 self.__class__ 的目的是什么?
【发布时间】:2014-01-03 03:53:40
【问题描述】:

检查self.__class__ 的目的是什么?我找到了一些创建抽象接口类的代码,然后检查它的self.__class__ 是否是它本身,例如

class abstract1 (object):
  def __init__(self):
    if self.__class__ == abstract1: 
      raise NotImplementedError("Interfaces can't be instantiated")

这样做的目的是什么? 是检查类是否是自身的类型吗?

代码来自NLTK的http://nltk.googlecode.com/svn/trunk/doc/api/nltk.probability-pysrc.html#ProbDistI

【问题讨论】:

  • 我认为这需要更多的上下文。您在哪里“找到”此代码?它基本上坏了。
  • @Iguananaut:为什么坏了?当按预期使用时,它工作很好;作为一个抽象基类。
  • 我很确定之前它是不同的东西?我不知道——我同意,现在那里的东西没有损坏。

标签: python class oop interface self


【解决方案1】:

您在此处发布的代码是无操作的; self.__class__ == c1 不是条件的一部分,因此会计算布尔值,但不会对结果进行任何处理。

您可以尝试创建一个抽象基类来检查 self.__class__ 是否等于抽象类而不是假设的子类(通过 if 语句),以防止抽象基类的实例化本身是由于开发者的错误。

【讨论】:

  • 尽管对于较新版本的 Python,应该只使用 abc.ABCMeta 的抽象基类。
  • ABC 仍然可以直接实例化。
【解决方案2】:

线索在类名“abstract1”和错误中。这旨在成为一个抽象类,这意味着一个旨在被子类化的类。每个子类都将提供自己的行为。抽象类本身用于记录接口,即实现接口的类预期具有的方法和参数。它本身并不意味着实例化,并且测试用于判断我们是在类本身还是子类中。

请参阅 Julien Danjou 撰写的 article 中有关抽象类的部分。

【讨论】:

    【解决方案3】:

    这样做的目的是什么?是检查类是否是自身的类型吗?

    是的,如果您尝试构造 Abstract1 类型的对象,它会抛出异常,告诉您不允许这样做。

    【讨论】:

      【解决方案4】:

      self.__class__ 是对当前实例的type 的引用。

      对于abstract1 的实例,那将是abstract1本身,这是抽象类所不希望的。抽象类只是为了被子类化,而不是直接创建实例:

      >>> abstract1()
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "<stdin>", line 4, in __init__
      NotImplementedError: Interfaces can't be instantiated
      

      对于abstract1子类 的实例,self.__class__ 将是对特定子类的引用:

      >>> class Foo(abstract1): pass
      ... 
      >>> f = Foo()
      >>> f.__class__
      <class '__main__.Foo'>
      >>> f.__class__ is Foo
      True
      

      在这里抛出异常就像在代码的其他地方使用assert 语句一样,它可以保护您免于犯愚蠢的错误。

      请注意,测试实例类型的 pythonic 方法是使用 type() function,以及带有 is 运算符的 identity 测试:

      class abstract1(object):
          def __init__(self):
              if type(self) is abstract1: 
                  raise NotImplementedError("Interfaces can't be instantiated")
      

      type() 应该优先于self.__class__,因为后者是can be shadowed by a class attribute

      在这里对自定义类使用相等测试没有什么意义,__eq__ 无论如何基本上都是作为身份测试实现的。

      Python 还包括一个标准库来定义抽象基类,称为abc。它允许您将方法和属性标记为抽象,并拒绝创建任何尚未重新定义这些名称的子类的实例。

      【讨论】:

        【解决方案5】:

        在 Python 3 中,使用 type() 检查类型或 __class__ 将返回相同的结果。

        class C:pass
        ci=C()
        print(type(ci)) #<class '__main__.C'>
        print(ci.__class__) #<class '__main__.C'>
        

        我最近检查了implementation 中的@dataclass 装饰器(Raymond Hettinger 直接参与了该项目),他们使用__class__ 来指代类型。

        所以使用__class__ 没有错 :)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-05-10
          • 1970-01-01
          • 1970-01-01
          • 2013-11-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多