2010-12-20 4 views
4


私は複数のサブクラスを派生させた基本クラスを持っています。
各サブクラスはクラス定数を定義しており、それらに対して一定の制限を適用したいと考えています。たとえば :派生時の自動クラス装飾(または検証)

class Base(object): 
    # define these in your sub-class, and make sure (NOM % DENOM == 0) 
    NOMINATOR = None 
    DENOMINATOR = None 

class Subclass_good(Base): 
    NOMINATOR = 6 
    DENOMINATOR = 3 

class Subclass_bad(Base): 
    NOMINATOR = 7 
    DENOMINATOR = 5 

は私がルール(NOM%のDENOM == 0)を強制することができるようにしたいです。
私は現在、クラスのデコレータでこれを行う:

def nom_denom_validator(cls): 
    assert(cls.NOMINATOR % cls.DENOMINATOR == 0) 
    return cls 

# and decorate each subclass, e.g.: 
@nom_denom_validator 
class Subclass_another(Base): 
    NOMINATOR = 9 
    DENOMINATOR = 12 

しかし、私は(私はたくさん持っている)各サブクラスを飾るために必要があるという事実が好きではありません。私はこれが基本クラスのいくつかの操作によって直接行うことができるかどうか興味があります。

アドバイスはありますか?あなたがSubclass_bad()のインスタンスを作成するときに、あなたがAssertionErrorを得るでしょう

class Base(object): 
    # define these in your sub-class, and make sure (NOM % DENOM == 0) 
    NOMINATOR = None 
    DENOMINATOR = None 
    def __init__(self): 
     assert(self.NOMINATOR % self.DENOMINATOR == 0) 

答えて

8

わかりました。私はしばらくそのことを考えていましたが、タグを選択して「メタクラス」を追加するときに質問を投稿した後で、自分で答えが出るかもしれません。

class Base_Metaclass(type): 
    def __new__(meta, classname, bases, class_dict): 
     new_type = type.__new__(meta, classname, bases, class_dict) 
     if not (new_type.NOMINATOR % new_type.DENOMINATOR) == 0: 
      raise Exception("Invalid subclass created - validation failed") 
     return new_type 

# have Base and all its descendants be enforced: 
class Base(object): 
    __metaclass__ = Base_Metaclass 
    # I must pass the validation myself, no None's anymore... 
    NOMINATOR = 1 
    DENOMINATOR = 1 

をそして今、すべての子どもたちは、自動強制する必要があります:
ので、レビューと今後の知識のために提出され、ここに行きます。

+4

あなたがクラスレベルの振る舞いを継承したい場合は、メタクラスが必要です。継承したくない場合は、クラスデコレータが必要です。 – Steve

1

あなたは基底クラスのコンストラクタにチェックを行うことができます。

+0

これは実際に悪いインスタンスを防ぐことができますが、私は "コンパイル時に"無効なサブクラス自体の作成を防ぐために探しています。 – Yonatan

+0

コンパイル時には実行できません。コンパイル時には構文エラーを検出しますが、メタクラス・ソリューションは実行時にクラスが定義されたときにチェックします。あるいは、ベース・クラス・コンストラクタをチェックインすると、実行時にも作成されます。 – Duncan

+0

@Duncan:あなたはもちろんです。私はインポート時にクラスオブジェクトの定義を参照していましたが、それは間違いなく実行時です。 – Yonatan

関連する問題