修改类中多个方法的调用参数

时间:2012-08-08 08:43:58

标签: python methods arguments

我有一个班级,也有很多方法。大多数方法都使用参数(总是使用相同的名称) - 我需要将参数的类型更改为其他类型,但是也希望接受参数的“旧”版本(和raise a {{ 1}})。

编辑我们可以假设参数始终作为关键字参数传递。

这种 DRY 最强的方式是什么?

我想到的第一个解决方案是:

DeprecationWarning

2 个答案:

答案 0 :(得分: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移至参数中的第一个位置

答案 1 :(得分: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")

这是一个非常丑陋的黑客攻击,但是应该可以工作并避免重新排序参数。

这里我使用一种检查来找到正确的参数并对其进行修改,无论它是作为关键字还是索引参数传递。

请注意,我稍微更改了测试以使其适用于我(我“弃用”整数并要求strs)。您只需要我的check_opp()功能并将其应用到您需要的任何位置。