2017-01-07 12 views
3

私は、メソッドが最初に属性が存在するかどうかを検証し、そうでなければそれを計算する関数を呼び出す必要があるクラスを持っています。次に、属性がNoneでないことを確認して、その属性でいくつかの操作を実行します。私はわずかに異なる2つの設計の選択を見ることができます:Pythonデザイン - クラス属性の初期化、設定、取得

最初の設計では
class myclass(): 
    def __init__(self): 
     self.attr = None 

    def compute_attribute(self): 
     self.attr = 1 

    def print_attribute(self): 
     if self.attr is None: 
      self.compute_attribute() 
     print self.attr 

そして

class myclass2(): 
    def __init__(self): 
     pass 

    def compute_attribute(self): 
     self.attr = 1 
     return self.attr 

    def print_attribute(self): 
     try: 
      attr = self.attr 
     except AttributeError: 
      attr = self.compute_attribute() 
     if attr is not None: 
      print attr 

、私が冗長になることができ、すべてのクラス属性を事前にNoneに設定されていることを確認する必要がありますオブジェクトの構造を明確にする。

2番目の選択肢は、より広く使用されているようです。しかし、私の目的(情報理論に関連する科学的コンピューティング)は、このクラスが実際に他のクラスとやりとりするわけではないので、少しでも過剰なものになることがあります。データを取り、多くのものを計算します。

+1

は、あなたがこのような何かをしたい、あなただけ__getattr__内の属性にアクセスするためにgetattrを使用していることを確認したり、無限再帰になってしまいます。http://stackoverflow.com/questions/3012421/python-memoising- deferred-lookup-property-decoratorです。クラス自体を印刷することは非常に非平凡ではありません。代わりに '__repr__'や' __str__'を実装してください。 – jonrsharpe

+0

各クラスオブジェクトは確かに属性 'attr'を持つべきであるので、ファーストクラスのデザインを使う方が良いです。これは、このクラスの属性は何かを明確にしています。 attrをクラス属性として設定することもできます。self.attrでアクセスするときは、attrのコピーを呑み込んでしまいます。perticularオブジェクトだけを設定/取得することもできます。 – Roshan

答えて

-1

the answer jonrsharpe linkedに基づいて、私は第3の設計選択肢を提供する。ここでのアイデアは、MyClassのクライアントまたはMyClass内のコードによって、特別な条件付きロジックが全く必要ないということです。代わりに、デコレータは、プロパティの(仮説的に高価な)計算を行う関数に適用され、その結果が格納されます。

これは、(クライアントがプロパティにアクセスしようとした場合にのみ)高価な計算が遅れて実行され、一度だけ実行されることを意味します。

def lazyprop(fn): 
    attr_name = '_lazy_' + fn.__name__ 

    @property 
    def _lazyprop(self): 
     if not hasattr(self, attr_name): 
      setattr(self, attr_name, fn(self)) 
     return getattr(self, attr_name) 

    return _lazyprop 


class MyClass(object): 
    @lazyprop 
    def attr(self): 
     print('Generating attr') 
     return 1 

    def __repr__(self): 
     return str(self.attr) 


if __name__ == '__main__': 
    o = MyClass() 
    print(o.__dict__, end='\n\n') 
    print(o, end='\n\n') 
    print(o.__dict__, end='\n\n') 
    print(o) 

出力

{} 

Generating attr 
1 

{'_lazy_attr': 1} 

1 

編集 OPのコンテキストにCyclone's answer

アプリケーション:

class lazy_property(object): 
    ''' 
    meant to be used for lazy evaluation of an object attribute. 
    property should represent non-mutable data, as it replaces itself. 
    ''' 

    def __init__(self, fget): 
     self.fget = fget 
     self.func_name = fget.__name__ 

    def __get__(self, obj, cls): 
     if obj is None: 
      return None 
     value = self.fget(obj) 
     setattr(obj, self.func_name, value) 
     return value 


class MyClass(object): 
    @lazy_property 
    def attr(self): 
     print('Generating attr') 
     return 1 

    def __repr__(self): 
     return str(self.attr) 


if __name__ == '__main__': 
    o = MyClass() 
    print(o.__dict__, end='\n\n') 
    print(o, end='\n\n') 
    print(o.__dict__, end='\n\n') 
    print(o) 

出力は上記と同じです。

+1

これは*とまったく同じではありません。この質問が重複していると思われる場合は、回答をコピーするのではなく、そのようにフラグを立ててください。 – jonrsharpe

+0

@jonrsharpe私はそれを重複として分類するのに十分な自信がありません(そうであれば、なぜ自分でそれを報告するのではなく、他の回答にリンクしましたか?)。しかし、それがまだOPに役立つかもしれないと考えてください(私は彼の要求に特別に合わせました)。彼が別の答えを受け入れるか、私の答えが-3になると、それを削除します。 – Tagc

+1

リンクされた質問では、それはまた、あとで - まだ私にはより不思議なようです - [回答](http://stackoverflow.com/a/6849299/5429658)が好ましいです。 –

0

まず、hasattrを使用して、オブジェクトに属性があるかどうかを確認し、属性が存在する場合はTrueを返します。

hasattr(object, attribute) # will return True if the object has the attribute 

第二に、あなたはPythonでの属性へのアクセスをカスタマイズすることができ、あなたはここでそれについての詳細を読むことができます:https://docs.python.org/2/reference/datamodel.html#customizing-attribute-access

基本的に、あなたはこれを達成する__getattr__メソッドをオーバーライドするので、何かのように:

クラスmyclass2(): DEF INIT(自己): パス

私が思う

+0

if hasattr(self、name)とgetattr(self、name)!= None: 'を実行すると、私は1行で必要なものすべてをチェックし、属性を設定したかどうかには依存しませんそうではないのですが、[this](https://hynek.me/articles/hasattr/)のような投稿を読んだ後は、「hasattr」は一般的に安全な選択肢ではないという印象を受けます。 –

+0

IMHO、それは本当にあなたのシステムに依存しています。たくさんのサードパーティのクラスに依存しているなら、おそらくいい考えではないかもしれませんが、そうでなければ、なぜあなたはそれを考慮することができません。 – Bitonator

+0

@PietroMarchesiもしあなたが 'getattr(self、name、None)がNoneでないことが必要ですね';デフォルトで 'getattr'は欠落している属性のために' AttributeError'をスローします。あなたはIDで 'None'をテストする必要があります。 – jonrsharpe

関連する問題