2017-11-07 5 views
0

私は(コード内の任意の問題を言い訳、メモリをオフに行く)などのデコレータを書いてみました:クラスの必須プロパティを定義するためのデコレータの作成方法

def required(fn): 
    def wrapped(self): 
     self.required_attributes += [fn.__name__] 
     fn(self) 

    return wrapped 

と私は例えば、クラスで@property属性を飾るためにこれを使用:

@property 
@required 
def some_property(self): 
    return self._some_property 

。今、私はこれがで更新するrequired_attributesためにために動作しないことを忘れてしまった

def validate_required_attributes(instance): 
    for attribute in instance.required_attributes: 
     if not hasattr(instance, attribute): 
      raise ValueError(f"Required attribute {attribute} was not set!") 

:私はこのような何かを行うことができることを..soプロパティの名前は、まずプロパティを取得する必要があります。だから本質的には、私がをクラスに入れると、self.propertynameを追加して追加することができます...しかし、この解決法はあまりうまくいきません。また、必要な属性名のリストを初期

デコレータはコンパイル時に適用されるので、ラップされた関数を定義する前にrequired_attributesを変更することはできません。私はこの仕事をすることができる別の方法はありますか?私はちょうど良い、エレガントなソリューションが欲しいです。

ありがとうございます!

+2

'def __init __(self、required_one、required_two)'の何が問題なのですか? –

答えて

0

私はattrs libraryと思っています。このようなクラスを定義できます。xyが必要です。zはオプションです。

from attr import attrs, attrib 

@attrs 
class MyClass: 
    x = attrib() 
    y = attrib() 
    z = attrib(default=0) 

テストそれアウト:

>>> instance = MyClass(1, 2) 
>>> print(instance) 
MyClass(x=1, y=2, z=0) 
0

ここでは、クラスのデコレータとメソッドのデコレータでそれをやっての私の感想です。おそらくメタクラスを使用してこれを行うより良い方法があります(APIは実装ではありません;))。これは、最初のプロパティに触れる、発信者を必要とせずに検証作業をしなければならない

def requiredproperty(f): 
    setattr(f, "_required", True) 
    return property(f) 


def hasrequiredprops(cls): 
    props = [x for x in cls.__dict__.items() if isinstance(x[1], property)] 
    cls._required_props = {k for k, v in props if v.fget._required} 
    return cls 


@hasrequiredprops 
class A(object): 

    def __init__(self): 
     self._my_prop = 1 

    def validate(self): 
     print("required attributes are", ",".join(self._required_props)) 

    @requiredproperty 
    def my_prop(self): 
     return self._my_prop 

>>> a = A() 
>>> a.validate() 
required attributes are my_prop 
>>> a.my_prop 
1 

クラスのデコレータは、それがインスタンス化duing必要なプロパティ名を持っていることを確認するために必要とされます。 requiredproperty関数は、必要に応じてプロパティをマークする単なる方法です。

私はあなたがここで達成しようとしていることを完全には分かっていません。おそらくプロパティが返すインスタンス属性値の検証ですか?

関連する問題