2016-09-06 1 views
2

私はPython 3.5です:ファンクションデコレータはdefの最初の2行を指定しますか?

私はいくつかの私のpythonの機能で繰り返しパターンを持っています。クラスの大規模なコレクションのために最初の2行は、次のとおりです。私はここでそれを簡素化するんだけど、obj_aobj_bを得るプロセスが1つのライナーではありません

obj_a = <..... obtain something I need.....> 
obj_b = <..... obtain another thing I need....> 

...私はこれを繰り返す避けたいですobj_aobj_bを得るためにどこにでもutilの機能よりも洗練された方法でコード(例えばobj_a = getObjectA() ...)

それらの行を取ると私は何かを持っている機能のデコレータの一部としてそれらを配置する方法はありますlike:

@function_where_I_need_my_objects 
def foo: 
    <....do something with obj_a and obj_b already initialized....> 
+0

私は、これらのオブジェクトを実行ごとに1回ではなくコマンドで生成する必要があると考えています。それ以外の場合は、関数へのオプションの引数を使用することができます。 –

+0

あなたはその前提について正しいです。ありがとう。 – JasonGenX

+0

デコレータを使用して、最初の行または関数の2つを定義するのではなく、細い空気の中にそれらを存在させたいのですか?もっとたくさんある場合は、2つの関数があるかもしれませんが、そうでなければ、あなたは 'a'と' b'は何も持っていないので、あなたが示唆している方法で動作するコードは読みにくいと思いますとにかく存在します。 –

答えて

1

obj_aobj_bはよく似た状態です。

class Thing: 
    def __init__(self): 
     # These could also be class attributes instead 
     # if they can be initialized when Thing is first 
     # defined. 
     self.obj_a = ... 
     self.obj_b = ... 

    def foo(self): 
     # use self.obj_a and self.obj_b 

t = Thing() 
t.foo() 

obj_aの周りにクロージャを返し、obj_bも可能ですデコレータを定義します。

def decorator(f): 
    obj_a = ... 
    obj_b = ... 
    def _(): 
     # use obj_a and obj_b 
    return _ 

@decorator 
def foo(): 
    ... 

しかし、それは長く、より柔軟単純にいずれかがその戻り二つのオブジェクト関数を記述はほとんどありません、そして、彼らは好きな名前、発信者の使用をすることができます:

def _get_a_b(): 
    a = ... 
    b = ... 
    return a, b 

def foo(): 
    obj_a, obj_b = _get_a_b() 
    ... 

def bar(): 
    a1, a2 = _get_a_b() 
    ... 
-3

することができます基本クラスでこれらの2つのオブジェクトを置く:

class TheBaseClass: 
    obj1 = something 
    obj2 = something_else 

し、必要なクラスの機能でこれを継承します。

class Class1(TheBaseClass): 
    def func1(self): 
     a = self.obj1 # make use of it 
     b = self.obj2 # make use of it 
+0

それらをインスタンス属性からクラス属性に変更するように変更すると、これはほとんど同じことではありませんが、その質問には答えません。 – martineau

-1

次のように、関数が呼び出されたときに効果的にローカルになる変数を作成することができます。これは、eval()を使用します。これは、信頼できない入力で使用すると危険ですが、装飾された関数のコンパイル済みバイトコード(ただし、caveat emptor)の実行には使用されません。

def local_vars(**kwargs): 
    """ Create decorator which will inject specified local variable(s) into 
     function before executing it. 
    """ 
    def decorator(fn): 
     def decorated(): 
      return eval(fn.__code__, 
         {k: v() for k, v in kwargs.items()}) # call funcs 
     return decorated 
    return decorator 

def get_object_a(): return 13 
def get_object_b(): return 42 

# create abbreviation for the long decorator 
obj_decorator = local_vars(obj_a=get_object_a, obj_b=get_object_b) 

@obj_decorator # apply decorator 
def test(): 
    print(obj_a) 
    print(obj_b) 

test() 

出力:

13 
42 
0

あなたは呼び出し可能なクラスの代わりに関数の、あなたは一つの場所に定型を保つことができるこの方法を使用することを検討し、そのベースのサブクラスとして他のものを実装してもよいです。

class BaseFoo: 

    def __init__(self): 
     # self.obj_a = <..... obtain something I need.....> 
     # self.obj_b = <..... obtain another thing I need....> 

class MyFoo(BaseFoo): 

    def __call__(self, *arg, **kwargs): 
     # <....do something with obj_a and obj_b already initialized....> 

foo = MyFoo() 
関連する問題