私は(もっと良い言葉の欠如のための)クラスのルータが必要です。
これにはクラスが必要ですか?それはクラスまたはインスタンスに属する場合
ルータはクラス&呼び出し、そのクラスのインスタンスの機能
をインスタンス化する必要があり、機能は通常、「法」と命名されます。それほど重要ではありませんが、物事がより明確になります。また、「インスタンス」は、明らかに常にクラスのインスタンスです。)
クラス関数を正しく定義するにはどうすればよいですか。 クラス関数を正しく呼び出すにはどうすればよいですか?
ルータは本当にである必要がありますか?しかし、とにかく...
ここにはいくつかの異なる問題があります(私はもちろん、十分な一般的なものが必要だと思います)。
最初のものは、あなたのクラス( "ルータ"によってインスタンス化されるもの)のコンストラクタがいくつかの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()
私はあなたの "ルータ"用語を保持していましたが、上記で説明したもののほとんどは既知のパターンです。 「プロキシ」、「プロキシー方式」、(最後の例では)「部分評価」を検索することができます。
クラスをまだ知っていないと、メソッドを正しく定義するにはどうすればよいですか?それでは、メソッド名ではなく変数を使ってオブジェクトを適切に呼び出す方法は? – Emily
"ルーティング"メソッドを直接呼び出す場合、クラスを使用するポイントは何ですか?単純な関数はまったく同じように動作します。 –
主な理由は、ルータのインスタンスがスレッド上で実行されるためです。何百ものスレッドがあります。各スレッドはルータの一意のインスタンスを必要とし、同時に動作する必要があります。私はクラスを使わずにそれをどうやって行うのか分からないのですか? – Emily