关于python中的泛型函数:python中的泛型函数 – 调用具有未知数量参数的方法

generic function in python - calling a method with unknown number of arguments

我对python不熟悉,需要帮助…

我正在实现一个通用搜索函数,它接受一个参数"边缘",它可以是多种类型的数据结构。

在搜索方法中,我有一行:

1
 fringe.push(item, priority)

问题是不同数据结构中的push方法采用不同数量的参数(有些需要优先级,有些不需要)。是否有一种Ellegant方法来传递该参数并使"push"方法只从发送的参数列表中获取所需的参数数量?

谢谢!


获取不同数量的参数并仍然能够选择正确参数的方法是使用*args和**关键字参数。从Mark Lutz的Learning Python书中:

* and **, are designed to support functions that take any number of arguments. Both can appear in either the function definition or a
function call, and they have related purposes in the two locations.

函数定义中的***

如果定义函数:

1
2
3
4
def f1(param1, *argparams, **kwparams):
    print 'fixed_params -> ', param1
    print 'argparams  --> ', argparams
    print 'kwparams   ---->,', kwparams

你可以这样称呼它:

1
f1('a', 'b', 'c', 'd', kw1='keyw1', kw2='keyw2')

然后你得到:

1
2
3
fixed_params ->  a
argparams  -->  ('b', 'c', 'd')
kwparams   ---->, {'kw1': 'keyw1', 'kw2': 'keyw2'}

这样您就可以发送/接收任意数量的参数和关键字。恢复关键字参数的一个典型习惯用法如下:

1
2
3
def f1(param1, **kwparams):
    my_kw1 = kwparams['kw1']
    ---- operate  with my_kw1 ------

通过这种方式,可以使用任意数量的参数调用函数,并使用它需要的参数。这种类型或参数在一些GUI代码(如Wxpython类定义和子类)中被频繁使用,也被用于函数转换、修饰等。

函数调用中的***

函数调用中的***参数在被函数接受时被解包:

1
2
3
4
5
6
7
8
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)来找出该方法采用的参数。这将告诉您可以传递的参数数量,但这非常混乱:

1
2
3
4
5
argspec = inspect.getargspec(fringe.push)
if len(argspec.args) >= 3 or argspec.varargs or argspec.keywords:
    fringe.push(item, priority)
else:
    fringe.push(item)

更简单的方法就是去追求它,必要时请求原谅:

1
2
3
4
try:
    fringe.push(item, priority)
except TypeError:
    fringe.push(item)

当然,最好还是确保push()方法都有一个一致的参数规范,但是如果不能这样做,那么就使用try...except


尝试下面的代码段,

1
2
3
4
5
6
7
8
9
def push(item, priority=None):
    print item,priority


args = (1,)
push(*args)

args = (1,2)
push(*args)

不能只使用默认参数值吗?

1
2
3
4
5
6
7
8
>>> def foo(a, b = 10):
...   print a, b
...
>>> foo(1000)
1000 10
>>> foo(1000, 1000)
1000 1000
>>>

如果没有提供参数b,则默认为10