1

私には(あまりにも)多くのメソッドがあるクラスがあります。raiseほとんどのメソッドは引数を取ります(常に同じ名前)-パラメーターのタイプを別のものに変更する必要がありますが、パラメーターの「古い」バージョン(およびDeprecationWarning)も受け入れたいと思います。

編集引数は常にキーワード引数として渡されると想定できます。

これを行う最も乾燥した方法は何ですか?

私の頭に浮かぶ最初の解決策は次のようなものです。

def check_orc(orc):
    if isinstance(Snaga, orc):
        orc = convert_to_urukhai(orc)
        raise DeprecationWarning("You should not be sending snaga to combat")
    return orc

class Warrior():
    def slash_orc(sword, shield, opponent):
       opponent = check_orc(opponent)
       ...

    def hack_orc(warhammer, opponent):
       opponent = check_orc(opponent)
       ...
4

2 に答える 2

4

avasalのコメントは正しいです。ただし、教育目的のために、ここにあなたが望むもののデコレータ実装があります:

from functools import wraps

def convert_orc(f):
    @wraps(f)
    def wrapper(self, opponent, *args, **kwargs):
        if isinstance(Snaga, orc):
            raise DeprecationWarning(...)
            return f(self, convert_to_urukhai(opponent), *args, **kwargs)
        else:
            return f(self, opponent, *args, **kwargs)
    return wrapper

class Warrior():
    @convert_orc
    def slash_orc(self, opponent, sword, shield):
       ...

    @convert_orc
    def hack_orc(self, opponent, warhammer):
       ...

注:opponentパラメーターの最初の位置に移動しました

于 2012-08-08T08:55:10.523 に答える
2

これが常に最後のパラメーターかどうかわかりますか? そうでない場合は、その名前で作業する必要があります。

私の考えはこれを行うことです:

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()機能が必要なだけで、必要な場所に適用できます。

于 2012-08-08T09:04:02.403 に答える