web-dev-qa-db-ja.com

self .__ class__をチェックする目的は何ですか? -python

チェックの目的は何ですか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

19
alvas

_self.__class___は、現在のインスタンスのtypeへの参照です。

_abstract1_のインスタンスの場合、これは_abstract1_クラスitselfになります。これは、抽象クラス。抽象クラスは、インスタンスを直接作成するのではなく、サブクラス化することのみを目的としています。

_>>> 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___よりも優先される必要があります。後者は クラス属性によって隠される可能性があるため だからです。

カスタムクラスの場合と同様に、ここでは等価テストを使用する意味はほとんどありません。基本的に、___eq___は基本的にアイデンティティテストとして実装されます。

Pythonには abc と呼ばれる抽象基本クラスを定義する標準ライブラリも含まれています。メソッドとプロパティを抽象としてマークし、それらの名前をまだ再定義していないサブクラスのインスタンスの作成を拒否します。

23
Martijn Pieters

そこに投稿したコードは何もしません。 self.__class__ == c1は条件の一部ではないため、ブール値は評価されますが、結果は何も行われません。

抽象基本クラス自体のインスタンス化を防ぐために、self.__class__が(ifステートメントを介して)仮説の子ではなく、抽象クラスと等しいかどうかを確認する抽象基本クラスを作成することもできます。開発者のミスによる。

1

何人かはそうするだろうと私は言うでしょう:

class Foo(AbstractBase):
    def __init__(self):
        super(Foo, self).__init__()
        # ...

ベースが抽象であっても、ベースの__init__NotImplementedErrorをスローしないようにする必要があります。ねえ、多分それは何か便利なことでもありますか?

1
Kos

その目的は何ですか?クラスがそれ自体のタイプであるかどうかをチェックすることですか?

はい、タイプAbstract1のオブジェクトを作成しようとすると、その例外がスローされ、許可されていないことが通知されます。

1

Python 3では、type()を使用してタイプを確認するか、__class__を使用しても同じ結果が返されます。

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

私は最近@dataclassデコレータの implementation をチェックしました(レイモンドヘッティンガーはそのプロジェクトに直接関与しています)。型を参照するために__class__を使用しています。

したがって、__class__を使用することは間違いありません:)

0
prosti

手がかりは、クラスの名前「abstract1」とエラーにあります。これは、抽象クラス、つまりサブクラス化されることを意図したものです。各サブクラスは独自の動作を提供します。抽象クラス自体は、インターフェイス、つまりインターフェイスを実装するクラスが持つことが期待されるメソッドと引数をドキュメント化するのに役立ちます。それ自体がインスタンス化されることを意図したものではなく、テストは、クラス自体にあるのかサブクラスにいるのかを示すために使用されます。

Julien Danjouによる、この article の抽象クラスに関するセクションを参照してください。

0
Peter Westlake