问题描述
function test_function(foo::Int,bar::String)
#...
end
params = Dict(
"foo" => 1,"bar" => "baz"
)
在 Python 中,我可以像这样将所有参数作为 kwarg 传递:
def test_function(foo: int,bar: str):
#...
params = {
"foo": 1
"bar": "baz"
}
test_function(**params)
julia> test_function(params...)
ERROR: MethodError: no method matching test_function(::Pair{String,Any},::Pair{String,Any})
有没有办法在 Julia 中做类似的事情?
解决方法
Julia 明确区分了位置参数和关键字参数。为了澄清区别,您可以使用分号将位置参数与关键字参数分开。您可以使用 ...
(称为 splatting operator)将对象解包为位置参数或关键字参数。
如果要将对象解包为关键字参数,则它需要是成对或元组的迭代器。如果将对象解包为位置参数,则解包的元素类型需要匹配函数的方法之一。
这是一个例子:
function foo(x,y; a=1,b=2)
x + y + a + b
end
t = (1,2)
d = Dict(:a => 3,:b => 4)
julia> foo(t... ; d...)
10
但是,请注意字典中的键(或对/元组的迭代器)必须是符号,以便解包为关键字参数才能工作:
julia> e = Dict("a" => 3,"b" => 4);
julia> foo(t... ; e...)
ERROR: MethodError: Cannot `convert` an object of type String
to an object of type Symbol
有关详细信息,请参阅手册的 Varargs 和 Keyword Arguments 部分。
,编辑:哎呀在卡梅伦回答之后发布了这个。我会把它留在这里以防它有帮助,但老实说,它和他的回答说的几乎一样:-)
在 Julia 中,通用函数签名是 f(args ; kwargs)
。常规输入参数 args
的名称并不重要,重要的是它们在函数签名中出现的顺序。相比之下,对于关键字参数 kwargs
,名称很重要,顺序并不重要。
我们需要的最后一条信息是,对于 args
或 kwargs
,splatting 运算符 ...
将容器的元素分离为函数签名的单个参数.
所以,让我们将这一切应用到您的示例中。考虑以下两个函数:
function f1(foo::Int,bar::String)::String
return "$(foo) --> $(bar)"
end
function f2( ; foo::Int=0,bar::String="nil")::String
return "$(foo) --> $(bar)"
end
第一个函数只有args
,而第二个函数只有kwargs
。在第一个函数的情况下,名称无关紧要,因为我们正在处理 args
,因此为了生成容器,我们只需使用向量或元组,例如:
params = [1,"baz"]
f1(params...)
第二个函数只有 kwargs
,并且 Julia 希望看到这些表达为某些 Pair{Symbol,T}
的类型 T<:Any
。因此,如果我们构建字典以将关键字参数的名称(表示为 Symbol
)映射到值,那么 splatting 运算符会将字典的每个条目放入函数签名中,如下所示:
params = Dict(:foo=>1,:bar=>"baz")
f2(; params...)
请注意,我必须在函数调用中使用 ;
来表示没有 args
,只有 kwargs
。
当然,如果需要,您可以同时拥有两者,例如f3(vectorofargs... ; dictofargs...)
。