Python 修改类中多个方法的调用参数
我有一个类,它有(太)多的方法。大多数方法都使用一个参数(总是相同的名称)-我需要将参数的类型更改为其他类型,但也希望接受参数的“旧”版本(以及Python 修改类中多个方法的调用参数,python,methods,arguments,Python,Methods,Arguments,我有一个类,它有(太)多的方法。大多数方法都使用一个参数(总是相同的名称)-我需要将参数的类型更改为其他类型,但也希望接受参数的“旧”版本(以及raiseaDeprecationWarning) 编辑:我们可以假设参数始终作为关键字参数传递 最干燥的方法是什么 我想到的第一个解决方案是: def check_orc(orc): if isinstance(Snaga, orc): orc = convert_to_urukhai(orc) raise De
raise
aDeprecationWarning
)
编辑:我们可以假设参数始终作为关键字参数传递
最干燥的方法是什么
我想到的第一个解决方案是:
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)
...
阿瓦萨尔的评论是正确的。但是,出于教育目的,以下是您想要的装饰器实现:
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):
...
注意:我将
对手
移动到参数中的第一个位置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):
...
注意:我将
对手
移动到参数中的第一个位置您能告诉我这是否始终是最后一个参数吗?如果没有,你就得用它的名字
我的想法是这样做:
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()
函数,并将其应用于任何需要的地方。您能告诉我这是否始终是最后一个参数吗?如果没有,你就得用它的名字
我的想法是这样做:
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()
函数,并将其应用到您需要的任何地方。将最常用的参数添加到self,这样您就可以避免所有方法都传递它。或者,您很难通过sed命令编辑源代码。这不是干巴巴的,而是更具可读性和可维护性。我不明白-当它是实例的外部实体时,如何将参数添加到self
中?将最常用的参数添加到self中,这样可以避免通过所有方法传递它。或者,您很难通过sed命令编辑源代码。这不是干巴巴的,而是更具可读性和可维护性。我不明白-当它是实例的外部实体时,我如何才能将参数添加到self
?+1,但我在brainf*ck:)中看到了更好看的代码,这真是太难看了@JoelCornett是的,它是:-)但是如果对手有时在这里,有时在那里,你几乎没有其他选择…对手总是一个关键字参数(或者如果不是,我可以这样做)+1,但我在brainf*ck:)中看到了更好看的代码,那真是太难看了@JoelCornett是的,它是:-)但是如果对手时而在这里时而在那里,你几乎没有其他选择…对手总是一个关键字参数(如果不是,我可以这样做)