2017-11-02 4 views
0

私は@property別のデコレータ

def android(**params): 
    def deco(f): 
     def wrap(*args, **kwargs): 
      if is_android: 
       return params 
      return f() 
     return wrap 
    return deco 

def ios(**params): 
    def deco(f): 
     def wrap(*args, **kwargs): 
      if not is_android: 
       return params 
      return f() 
     return wrap 
    return deco 

と定義されたクラスでは動作し、これらのデコレータを持っていると@property組み合わせ:私は、私が使用するたびに、再び繰り返し、再び@propertyする必要が

class Foo: 
    @property 
    @android(foo=1) 
    @ios(foo=2) 
    def foo(self): 
     pass 

f = Foo() 
print(f.foo) 

@android@ios@propertyを結合する方法はありますか?私はちょうど意味@propertyなし@android@iosを使用する必要があるが、私はあなたがpropertyオブジェクトを返すためにデコレータを変更することができますf.foo

+1

探しているものである

is_android = True def android(**params): def deco(f): def wrap(*args, **kwargs): if is_android: return params return f() wrap.__decorated_by_mobile__ = True return wrap return deco def ios(**params): def deco(f): f.wrapped = True def wrap(*args, **kwargs): if not is_android: return params return f() wrap.__decorated_by_mobile__ = True return wrap return deco def class_deco(cls): for name, method in cls.__dict__.items(): if callable(method): if hasattr(method, '__decorated_by_mobile__'): setattr(cls, name, method()) return cls @class_deco class Foo: @android(a=1) @ios(a=2) def foo(self): pass f = Foo() print(f.foo) 

希望は、あなたは必ずこれらの作品はありますか?インデントがオフに見え、内部関数を返さない... TypeError: 'NoneType'オブジェクトが私のコンピュータ上で呼び出し可能ではない 'をスローする。 – MSeifert

+0

私は少しコードを編集します。私のコンピュータでは、コードが機能しました。 –

+0

うまくいけば、正確に何が返ってくるのですか? – MSeifert

答えて

1

私はあなたがプロパティは、クラスのフィールドも作るためにあなたのクラスを変更クラスのデコレータを使用する必要があると思います。まったく予想通り、これはあなたが:)

+0

これはかなりうまく動作します。ありがとう –

1

を呼び出すことができています。あなただけの彼らのために、単一の特定の順序をサポートする場合を除きしかし、あなたは、彼らがに適用されている「機能」は、既にプロパティオブジェクトの場合でも動作するように彼らのロジックが少し複雑にする必要があります。

def android(**params): 
    def deco(f): 
     if isinstance(f, property): 
      prop = f.getter 
      f = f.fget 
     else: 
      prop = property 
     def wrap(*args, **kwargs): 
      if is_android: 
       return params 
      return f() 
     return prop(wrap) 
    return deco 

しかし、私はそれが本当に最善の方法だか分からない:ここで私はそれを行うべきだと思うあなたのデコレータの1のテストされていないアップデートです。あなたのコードはあなたが飾るfoo関数を使用することはありません。デコレータの1つが常にコールをインターセプトします。それがあなたの実際のコードに当てはまるならば、私は自分自身の記述子型を書いて、propertyやデコレータでは気にしないことをお勧めします。ここでは、引数としてAndroidとiOSの場合に返すための値をとるカスタム記述子の非常に単純な例です(そしてそれは、クラスでの使用です):

class MyDescriptor: 
    def __init__(self, android_value, ios_value): 
     self.android_value = android_value 
     self.ios_value = ios_value 

    def __get__(self, instance, owner) 
     if is_android: 
      return self.android_value 
     else: 
      return self.ios_value 

    def __set__(self, instance, value): 
     raise NotImplementedError() 

class Foo: 
    foo = MyDescriptor({"foo": 1}, {"foo": 2}) 

あなたもis_android場合、物事を単純化に向けて、さらに行くことができます値は定数であり、クラスが定義されている時点でその値が分かる場合は、そのような状況では、あなただけの、必要に応じて値を変更するために、条件付きロジックを使用して、通常のクラス変数を割り当てることができます。

class Foo: 
    foo = {"foo": 1 if is_android else 2} 
+0

あなたのソリューションは私が以前にしたものでした。私はandroidとios paramsを持つ関数を定義しました。それから戻ってください。しかし、読むのは難しかったです。それで私は '@property 'を思いついたのです –