これが常に最後のパラメーターかどうかわかりますか? そうでない場合は、その名前で作業する必要があります。
私の考えはこれを行うことです:
def check_orc(orc):
if isinstance(orc, int):
orc = str(orc)
print DeprecationWarning("You should not be sending snaga to combat")
return orc
def check_opp(meth):
code = meth.func_code
argnames = code.co_varnames[:code.co_argcount]
if 'opponent' in argnames:
from functools import wraps
argidx = argnames.index('opponent')
@wraps(meth)
def replace(*a, **k):
if 'opponent' in k:
k['opponent'] = check_orc(k['opponent'])
else:
a = list(a)
a[argidx] = check_orc(a[argidx])
a = tuple(a)
return meth(*a, **k)
return replace
else:
return meth
class Warrior():
@check_opp
def slash_orc(self, sword, shield, opponent):
print "slash", (sword, shield, opponent)
@check_opp
def hack_orc(self, warhammer, opponent):
print "hack", (warhammer, opponent)
Warrior().slash_orc(1,3,4)
Warrior().hack_orc(6,5)
Warrior().slash_orc(1,3,opponent=4)
Warrior().hack_orc(6,opponent=5)
Warrior().slash_orc(1,3,"4")
Warrior().hack_orc(6,"5")
Warrior().slash_orc(1,3,opponent="4")
Warrior().hack_orc(6,opponent="5")
これは非常に醜いハックですが、それでも機能するはずであり、パラメーターを並べ替える必要がありません。
ここでは、キーワードまたはインデックス付き引数として渡されたかどうかに関係なく、正しいパラメーターを見つけて変更するために一種の検査を使用します。
テストを機能させるために、テストを少し変更したことに注意してください(intを「非推奨」にし、strを必要とします)。私のcheck_opp()
機能が必要なだけで、必要な場所に適用できます。