2016-10-21 15 views
0

クラス・ルーターが必要です(より良い単語がないため)。ルータは、クラス&をインスタンス化する必要があります。このクラスインスタンスに渡された変数に基づいてそのクラスインスタンスの関数を呼び出します。変数からクラス関数を呼び出す方法

クラス機能を正しく定義するにはどうすればよいですか?

クラス関数を正しく呼び出すにはどうすればよいですか?

例コード:

class ClassWorker1: 

    def function_1(self): 
     print('1a') 

    def function_2(self): 
     print('2a') 

    def function_3(self): 
     print('3a') 


class ClassWorker2: 

    def function_1(self): 
     print('1b') 

    def function_2(self): 
     print('2b') 

    def function_3(self): 
     print('3b') 


class ClassRouter(object): 
    def __init__(self, class_name, class_function): 
     self.class_instance = class_name() 
     self.class_function = class_function 
     self.main() 

    def main(self): 
     # how should I call the class function here? 
     self.class_instance.class_function() 
     return 


a = 1 
b = 1 


if a == 1: 
    class_name = ClassWorker1 
else: 
    class_name = ClassWorker1 

if b == 1: 
    # Strings won't work as class function definition 
    # I won't know the class at this point. I will only know 
    # the shared function name at this point. 
    # how could this class function be defined directly? 
    class_function = 'function_1' 

elif b == 2: 
    class_function = 'function_2' 

else: 
    class_function = 'function_3' 


ClassRouter(class_name, class_function) 
+0

クラスをまだ知っていないと、メソッドを正しく定義するにはどうすればよいですか?それでは、メソッド名ではなく変数を使ってオブジェクトを適切に呼び出す方法は? – Emily

+0

"ルーティング"メソッドを直接呼び出す場合、クラスを使用するポイントは何ですか?単純な関数はまったく同じように動作します。 –

+0

主な理由は、ルータのインスタンスがスレッド上で実行されるためです。何百ものスレッドがあります。各スレッドはルータの一意のインスタンスを必要とし、同時に動作する必要があります。私はクラスを使わずにそれをどうやって行うのか分からないのですか? – Emily

答えて

2

私は(もっと良い言葉の欠如のための)クラスのルータが必要です。

これにはクラスが必要ですか?それはクラスまたはインスタンスに属する場合

ルータはクラス&呼び出し、そのクラスのインスタンスの機能

をインスタンス化する必要があり、機能は通常、「法」と命名されます。それほど重要ではありませんが、物事がより明確になります。また、「インスタンス」は、明らかに常にクラスのインスタンスです。)

クラス関数を正しく定義するにはどうすればよいですか。 クラス関数を正しく呼び出すにはどうすればよいですか?

ルータは本当にである必要がありますか?しかし、とにかく...

ここにはいくつかの異なる問題があります(私はもちろん、十分な一般的なものが必要だと思います)。

最初のものは、あなたのクラス( "ルータ"によってインスタンス化されるもの)のコンストラクタがいくつかのargs - positionまたはnamedまたはその両方を必要とすることです。クラスをインスタンス化するのはルーターの義務である(しかし、それはすべきでしょうか?)場合、それらのargs(位置と名前の両方)をルーターに渡す必要があります。あなたのルータは一般的なものでなければならない(そうでなければ役に立たない)ので、あなたのルータのコンストラクタで明示的にこれらの引数を指定することはできません。

すなわち、通話時にそれぞれ***演算子を使用して、関数を呼び出すときにうまくいけば、Pythonは(という名前の引数のために)(位置引数のための)タプルとdictsを「解凍」する方法があります:

def somefunc(arg1, arg2, arg3="foo", arg4=None): 
    print arg1, arg2, arg3, arg4 

args = ("one", "two", "three") 
kwargs = {"arg4": "four"} 
somefunc(*args, **kwargs) 

これにより、関数に引数を汎用的に渡すことができます。

class Router(object): 
    def __init__(self, cls, clsargs=None, clskwargs=None): 
     if clsargs is None: 
      clsargs =() 
     if clskwargs is None: 
      clskwargs = {} 
     self._obj = cls(*clsargs, **clskwargs) 


class Worker(object): 
    def __init__(self, name): 
     self.name = name 
      print self.name 


r = Router(Worker, clsargs=("foo",)) 
# or 
r = Router(Worker, clskwargs={"name":"foo"}) 

は今、この時点で、あなたが本当に何を得ていないことに注意してください。

だから、あなたはあなたのルータが「ターゲット」クラスをinstanciatingを担当することにしたい場合は、これをサポートする必要があります(より多くのコードを除いて)ルータをインスタンス化することからあなたはWorkerクラスを持っている必要があるので、ルータをインスタンス化するためのコンストラクタのargsを持っているので、Workerインスタンスをルータに直接渡すことができます:

ルータに渡されたクラスへの参照が必要です(それ以外の場合は渡すことはできません)。

class Router(object): 
    def __init__(self, obj): 
     self._obj = obj 

class Worker(object): 
    def __init__(self, name): 
     self.name = name 
      print self.name 

r = Router(Worker("foo")) 
# or 
r = Router(Worker(name="foo")) 

それは労働者インスタンス化ルータを持つように理にかなって例は次のとおりです。

1 /ワーカーのコンストラクタの引数は、ルータがインスタンス化されたときに知られていないと、後に渡されることをしている場合(ました

2 /労働者のインスタンス化に非常にコストがかかり、あなたが実際にそれを必要とするかどうかわからない場合は、ルータの "メイン"メソッドが呼び出されて作業者がインスタンス化されます。

第2の問題は、「名前で作業者のメソッドを取得する方法」です。これは既にルーカスによって答えられました:あなたはgetattr(obj, attrname)を使用します。

第3の問題は、「私のワーカーメソッドに引数が必要な場合、どのように渡すか」です。これは、ワーカーのコンストラクタ引数と同じ問題です。したがって、解は明らかに同じです。具体的なユースケースに応じて、ルータをインスタンス化するとき、またはそれを "main"メソッドと呼ぶときに、それらのargを渡す必要があります。

WRT /この「メイン」の方法、あなたはそう、それはあなたのルータの「主要な」方法としてこれを使用する意味がありますすなわち

class NotAFunc(object): 
    def __init__(self, wot): 
     self.wot = wot 

    def __call__(self, count): 
     print self.wot * count 


notafunc = NotAFunc("wot ? ") 
notafunc(42) 

__call__方法を実装することで、独自の呼び出し可能なタイプを定義することができることを覚えておいてください

ルータクラスが本当に必要ですか? Python関数は独自のオブジェクトであるため(関数が関数を取り、関数を返す)、さらにはクロージャとして機能します(クロージャは、定義されている環境の一部を「取得」する関数です):

def route(instance, methodname, methargs=None, methkwargs=None): 
    method = getattr(instance, methodname) 
    if methargs is None: 
     methargs =() 
    if methkwargs is None: 
     methkwargs = {} 
    def func(): 
     return method(*methargs, **methkwargs) 
    return func 

class Worker(object): 
    def __init__(self, name): 
     self.name = name 

    def work(self, count): 
     return [self.name for i in range(count)] 


r = route(Worker("foo"), "work", (42,)) 
print r() 

私はあなたの "ルータ"用語を保持していましたが、上記で説明したもののほとんどは既知のパターンです。 「プロキシ」、「プロキシー方式」、(最後の例では)「部分評価」を検索することができます。

+0

ルータをスレッディングしている場合でもまだ関数を使用しますか? – Emily

+0

ルータコンストラクタは、インスタンスに渡される変数にも追加されます。インスタンス化の前に、ルータは "セットアップ"&afterwordも "クリーンアップ"作業を行います。関数とデコレータでこれを行うことができると思いますか?しかし、クラスは最善の解決策に見えました。そのことを念頭において、あなたはまだ関数を使用しますか? – Emily

+0

@Emilyもちろん、私はクラスを使用します - たとえ読みやすくするためであっても。また、あなたの最初の質問:あなたがPythonに慣れていない場合(おそらくあなたの質問がある場合)、スレッドを使う前に2度考えることができます - ほとんどの場合、Pythonであまり購入しません"グローバルインタプリタロック")ので、サブプロセスを使うほうが良いかもしれません。ここで再びそれはあなたが提供していない文脈に依存しますが、私はそれが有用な情報になると思った... –

1

あなたは動的属性の検索を探しています。

class C: 
    def c1(self, x): 
     return 2*x 

instance = C() 
method_name = 'c1' 

method = getattr(instance, method_name) 
print(method(1)) # call method and print result 
0

(new-style!)クラスの__new__メソッドをオーバーライドする必要があります。

class ClassRouter(object): 
    def __new__(self, class_name, *args): 
     if arg=="Class1": 
      new_instance = ClassWorker1(*args) 
      new_instance.method() 
      return new_instance 
     elif arg=="Class2": 
      return ClassWorker2(*args) 
関連する問題