1

ABC から継承するクラスのメソッドが適切なデコレータを使用して作成されるようにする方法を見つけようとしています。ABC が一般的にどのように機能するかを (できれば) 理解しています。

from abc import ABCMeta, abstractmethod

class MyABC(metaclass=ABCMeta):
    @abstractmethod
    def my_abstract_method(self):
        pass

class MyClass(MyABC):
    pass

MyClass()

これにより、「TypeError: 抽象メソッド my_abstract_method で抽象クラス MyClass をインスタンス化できません」というメッセージが表示されます。なるほど、なるほど。その名前でメソッドを作成するだけです。

class MyClass(MyABC):
    def my_abstract_method(self):
        pass

MyClass()

ブーム。あなたは終わった。しかし、この場合はどうですか?

from abc import ABCMeta, abstractmethod

class MyABC(metaclass=ABCMeta):    
    @property
    @abstractmethod
    def my_attribute(self):
        pass

class MyClass(MyABC):
    def my_attribute(self):
        pass

MyClass()

my_attribute はプロパティではありませんが、MyClass() 呼び出しは機能します。最終的に ABC が行うことは、指定された名前のメソッドが存在することを確認することだと思います。それでおしまい。さらに詳しく知りたい場合は、MyABC のソース コードを見て、ドキュメントを読む必要があります。そこにあるデコレータとコメントは、サブクラスをどのように構築する必要があるかを知らせます。

私はそれを正しく持っていますか、それともここで何かが欠けていますか?

4

1 に答える 1

2

ABCがそれを強制していないのは正しいです。「特定のデコレータを持っている」などを強制する方法はありません。デコレーターは、オブジェクトを返す関数です (たとえば、propertyプロパティ オブジェクトを返します)。ABCMeta は、クラスで定義された属性が特定のものであることを保証するために何もしません。それらがそこにあることを確認するだけです。これはエラーなしで「機能」します。

class MyABC(metaclass=ABCMeta):
    @abstractmethod
    def my_abstract_method(self):
        pass

class MyClass(MyABC):
    my_abstract_method = 2

MyClass()

つまり、ABCMeta は、サブクラスで提供される抽象メソッドがメソッドであることをまったく保証しません。その名前を持つある種の属性が必要です。

確かに、特定の属性が特定の種類の値を持つことを確認するために、より洗練されたチェックを行う独自のメタクラスを作成することもできますが、それは ABCMeta の範囲を超えています。

于 2016-08-09T05:45:50.370 に答える