Julia:是否可以将参数字典传递给函数?

时间:2021-05-07 02:01:11

标签: types arguments julia metaprogramming keyword-argument

我有一个要传递给函数的函数参数字典。例如:

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)

但是当我尝试 params... 时,出现以下错误:

julia> test_function(params...)
ERROR: MethodError: no method matching test_function(::Pair{String,Any}, ::Pair{String,Any})

有没有办法在 Julia 中做类似的事情?

2 个答案:

答案 0 :(得分:7)

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

有关详细信息,请参阅手册的 VarargsKeyword Arguments 部分。

答案 1 :(得分:4)

编辑:哎呀在卡梅伦回答之后发布了这个。我会把它留在这里以防它有帮助,但老实说,它和他的回答说的几乎一样:-)

在 Julia 中,通用函数签名是 f(args ; kwargs)。常规输入参数 args 的名称并不重要,重要的是它们在函数签名中出现的顺序。相比之下,对于关键字参数 kwargs,名称很重要,顺序并不重要。

我们需要的最后一条信息是,对于 argskwargs,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...)

相关问题