【发布时间】:2011-11-16 18:55:57
【问题描述】:
我是 python 新手,需要一些帮助...
我正在实现一个接受参数“边缘”的通用搜索函数,它可以是多种类型的数据结构。
在搜索方法中我有一行:
fringe.push(item, priority)
问题在于不同数据结构中的 push 方法采用不同数量的参数(有些需要优先级,有些不需要)。有没有一种优雅的方法可以通过它并使“推送”方法仅从发送的参数列表中获取它需要的参数数量?
谢谢!
【问题讨论】:
我是 python 新手,需要一些帮助...
我正在实现一个接受参数“边缘”的通用搜索函数,它可以是多种类型的数据结构。
在搜索方法中我有一行:
fringe.push(item, priority)
问题在于不同数据结构中的 push 方法采用不同数量的参数(有些需要优先级,有些不需要)。有没有一种优雅的方法可以通过它并使“推送”方法仅从发送的参数列表中获取它需要的参数数量?
谢谢!
【问题讨论】:
获得不同数量的参数并且仍然能够选择正确的方法是使用 *args 和 **keyword_args 参数。
来自 Mark Lutz 的 Learning Python 书:
*和**旨在支持采用任意数量参数的函数。两者都可以出现在函数定义或 函数调用,在这两个地方都有相关的用途。
* 和 ** 在函数定义中如果你定义一个函数:
def f1(param1, *argparams, **kwparams):
print 'fixed_params -> ', param1
print 'argparams --> ', argparams
print 'kwparams ---->,', kwparams
你可以这样称呼它:
f1('a', 'b', 'c', 'd', kw1='keyw1', kw2='keyw2')
然后你得到:
fixed_params -> a
argparams --> ('b', 'c', 'd')
kwparams ---->, {'kw1': 'keyw1', 'kw2': 'keyw2'}
这样您就可以发送/接收任意数量的参数和关键字。 恢复关键字 args 的一种典型习语如下:
def f1(param1, **kwparams):
my_kw1 = kwparams['kw1']
---- operate with my_kw1 ------
通过这种方式,您可以使用任意数量的参数调用您的函数,并使用它需要的参数。
这种类型或参数经常用于一些 GUI 代码,如 wxPython 类定义和子类化以及函数柯里化、装饰器等
* 和 ** 在函数调用中函数调用中的* 和** 参数在被函数获取时会被解包:
def func(a, b, c, d):
print(a, b, c, d)
args = (2, 3)
kwargs = {'d': 4}
func(1, *args, **kwargs)
### returns ---> 1 2 3 4
太棒了!
【讨论】:
理论上,您可以使用inspect.getargspec(fringe) 找出该方法采用的参数。这将告诉您可以传递的参数数量,但它非常混乱:
argspec = inspect.getargspec(fringe.push)
if len(argspec.args) >= 3 or argspec.varargs or argspec.keywords:
fringe.push(item, priority)
else:
fringe.push(item)
如果有必要,只要去争取并请求宽恕就简单多了:
try:
fringe.push(item, priority)
except TypeError:
fringe.push(item)
当然更好的是确保push() 方法都具有一致的参数规范,但如果您不能这样做,那么请使用try...except。
【讨论】:
试试下面的代码sn-ps,
def push(item, priority=None):
print item,priority
args = (1,)
push(*args)
args = (1,2)
push(*args)
【讨论】:
你不能只使用默认参数值吗?
>>> def foo(a, b = 10):
... print a, b
...
>>> foo(1000)
1000 10
>>> foo(1000, 1000)
1000 1000
>>>
如果没有提供参数b,则默认为10。
【讨论】:
try, except 块并尝试在没有参数的情况下运行.push。如果它坏了,试试这个参数。不过,我怀疑它会很快。