我对python不熟悉,需要帮助…
我正在实现一个通用搜索函数,它接受一个参数"边缘",它可以是多种类型的数据结构。
在搜索方法中,我有一行:
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.
函数定义中的*和**。
如果定义函数:
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'}
这样您就可以发送/接收任意数量的参数和关键字。恢复关键字参数的一个典型习惯用法如下:
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
伟大的!
这如何解决我认为是关于调用一个可能接受一个或两个参数但调用方不知道哪个参数的现有函数的问题?
@邓肯:如果你不知道要发送哪些参数,那么你要么反省这个方法,要么例外地尝试/失败,要么发送所有可能的已知参数,让不同的对象方法得到它们需要的参数。这最后一种方法是狭隘的,在许多情况下相当常见。对于OP示例,只需使用关键字默认参数就可以解决问题。由于我不确定OP是在谈论一个或两个论点,还是更一般的一个或多个论点,所以我给了他一个大概的观点,或是"args"和"kargs"。希望他觉得有用
如果您可以更改所调用函数的定义,这是一个很好的答案。如果没有,像@duncan这样的回答似乎是必要的。库开发人员可以通过让用户定义的回调方法采用*args和**kwargs来避免这个问题。这将允许您在将来无限期地向回调添加参数,而无需破坏任何内容或检查回调。
理论上,您可以使用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。
这种方法对我来说是必要的,当处理一个库时,我希望保持旧的回调签名向后兼容。在这种情况下,我有点担心捕获类型错误,因为我不知道它是来自回调签名还是来自用户回调代码中的某个异常。
尝试下面的代码段,
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。如果断开,请尝试参数。不过,我怀疑会很快。