我有一个班级,也有很多方法。大多数方法都使用参数(总是使用相同的名称) - 我需要将参数的类型更改为其他类型,但是也希望接受参数的“旧”版本(和raise
a {{ 1}})。
编辑:我们可以假设参数始终作为关键字参数传递。
这种 DRY 最强的方式是什么?
我想到的第一个解决方案是:
DeprecationWarning
答案 0 :(得分:4)
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()
功能并将其应用到您需要的任何位置。