2013-12-15 5 views
9

self.__class__をチェックする目的は何ですか?抽象的なインターフェイスクラスを作成し、そのself.__class__がそれ自身であるかどうかをチェックするコードをいくつか見つけました。self .__ class__をチェックする目的は何ですか? - python

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

目的は何ですか? クラスがそれ自身の型であるかどうかをチェックするのですか?

コードは、あなたが何-opがありません投稿NLTKのhttp://nltk.googlecode.com/svn/trunk/doc/api/nltk.probability-pysrc.html#ProbDistI

+1

これは、より多くの文脈を必要とすると思います。あなたはこのコードをどこで見つけましたか?それは基本的に壊れています。 – Iguananaut

+1

@Iguananaut:なぜそれは壊れていますか?意図どおりに使用された場合、* fine *動作します。抽象基本クラスとして。 –

+1

以前は何か違っていましたか?私は知らない - 私は同意する、今そこにあるものは壊れていない。 – Iguananaut

答えて

15

self.__class__は、現在のインスタンスのへの参照です。

abstract1のインスタンスの場合は、abstract1クラスそのものとなります。これは、抽象クラスでは望ましくないものです。抽象クラスのみ直接インスタンスを作成しない、サブクラス化されることを意図されている:

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

>>> 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__は、特定のサブクラスを参照するであろうここで例外を投げるのは、コード内の別の場所にあるassertステートメントを使うようなものです。間違いを犯さないように保護します。ニシキヘビ方法は、インスタンスのタイプをテストすること

isオペレータとアイデンティティ試験と共に、代わりtype() functionを使用することである:少しポイントであり

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

カスタムクラスの場合と同等のテストを使用すると、__eq__は基本的には本物のテストとして実装されます。

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

1

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

self.__class__が、抽象基底クラス自体のインスタンス化を防ぐために、(if文を使用して)仮説の子ではなく、抽象クラスと等しいかどうかをチェックする抽象基底クラスを作成できます開発者ミスのため

+1

最近のバージョンのPythonでは、 'abc.ABCMeta'を使って抽象基本クラスを使うだけです。 – Iguananaut

+0

ABCは引き続き直接インスタンス化できます。 –

1

私はいくつかがやるだろうと言うと思います:

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

ベースが抽象的である場合でも、あなたはベースの__init__NotImplementedErrorをスローするようにしたいとは思わないでしょう。ねえ、何か役に立つものさえあるかもしれない?

+0

'super(Foo、self).__ init __()'は動作しないと言っていますか?それは正しくないので、それはうまくいく*ちょうど良い*。ベースの '__init__'は、selfが' AbstractBase'のインスタンスであるときのみ例外をスローし、 'Foo'のようなサブクラスのインスタンスでは例外をスローしません。 –

0

手がかりは、クラス名 "abstract1"にあり、エラーにあります。これは、サブクラス化されることを意図した抽象クラスを意図しています。各サブクラスは独自の動作を提供します。抽象クラス自体は、インタフェース、すなわち、インタフェースを実装するクラスが有すると予想されるメソッドおよび引数を文書化するのに役立つ。これはインスタンス化されることを意図したものではなく、クラス自体かサブクラスかを調べるためにテストが使用されます。

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

1

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

はい、タイプAbstract1のオブジェクトを作成しようとすると、許可されていないという例外が送出されます。

関連する問題