2016-08-01 3 views
0

実行時に自動的にそのクラスをdictに登録するメタクラスを書きました。正常に動作するためには、抽象クラスを無視できる必要があります。Python 3でクラスが抽象クラスであるかどうかを調べる方法は?

コードは、Python 2に本当によく動作しますが、私は、Python 3

と互換性を持たせるためにしようとして壁に実行しました。ここのコードは、現在、次のようになります。

def AutoRegister(registry, base_type=ABCMeta): 
    class _metaclass(base_type): 
     def __init__(self, what, bases=None, attrs=None): 
      super(_metaclass, self).__init__(what, bases, attrs) 

      # Do not register abstract classes. 
      # Note that we do not use `inspect.isabstract` here, as 
      # that only detects classes with unimplemented abstract 
      # methods - which is a valid approach, but not what we 
      # want here. 
      # :see: http://stackoverflow.com/a/14410942/ 
      metaclass = attrs.get('__metaclass__') 
      if not (metaclass and issubclass(metaclass, ABCMeta)): 
       registry.register(self) 

    return _metaclass 
Pythonの2の

使い方は次のようになります。

# Abstract classes; these are not registered. 
class BaseWidget(object): __metaclass__ = AutoRegister(widget_registry) 
class BaseGizmo(BaseWidget): __metaclass__ = ABCMeta 

# Concrete classes; these get registered. 
class AlphaWidget(BaseWidget): pass 
class BravoGizmo(BaseGizmo): pass 

私はCAただし、Python 3でこの作業を行う方法はわかりません。

メタクラスがPython 3で抽象クラスを初期化するかどうかを判断するにはどうすればよいですか?

+0

'ABCMeta'の使用にもかかわらず、あなたが示すPython 2コードの"抽象的な "クラスは実際には抽象的ではありません(つまり、必要であればそれらのインスタンスを作成でき、Pythonでは例外が発生しません)。実際に抽象的なものにするには、その中で宣言するいくつかのメソッドで '@ abstractmethod'デコレータを使用する必要があります。子クラスも、それらのメソッドをオーバーライドしない限り(デコレータ自体を使用せずに)抽象クラスになります。この基本的な問題を最初に修正することなく、あなたの質問に純然たる答えを与えることができないのかどうかはわかりません。 – Blckknght

+0

私は入力をいただきありがとうございます。あなたのコメントは私にさらなる研究を促しました。私は「抽象」の私の最初の理解が間違っていたことを知りました。私はこれにいくつかの考えを与えなければならないでしょう。このパターンをコードベースで多く使用していますが、最終的に間違った方法でツールを使用すると、長期的に大きな問題が発生します。 – user5568265

答えて

0

PEP3119はどのようにABCMetaメタクラス「マーク」抽象メソッドを記述し、まだ抽象的であるクラスのすべてのメソッドが含まれている__abstractmethods__のfrozensetを作成します。したがって、クラスclsが抽象クラスであるかどうかを確認するには、cls.__abstractmethods__が空であるかどうかを確認してください。

また、this relevant post on abstract classesが役に立ちました。

関連する問題