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

Julia: Is it possible to pass a dictionary of parameters to a function?

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

function test_function(foo::Int, bar::String)
    #...
end

params = Dict(
    "foo" => 1,
    "bar" => "baz"
)

在 Python 中,我可以像这样将所有参数作为 kwargs 传递:

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 中做类似的事情?

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

但是,请注意字典中的键(或 pairs/tuples 的迭代器)必须是符号才能解包到关键字参数中:

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 and Keyword Arguments 部分。

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

在 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 希望看到这些表示为某些 T<:Any 的类型 Pair{Symbol,T}。因此,如果我们构建字典以将关键字参数的名称(表示为 Symbol)映射到值,则展开运算符会将字典的每个条目展开到函数签名中,如下所示:

params = Dict(:foo=>1, :bar=>"baz")
f2(; params...)

请注意,我必须在函数调用中使用 ; 来表示没有 args,只有 kwargs

当然,如果需要,您可以同时拥有两者,例如f3(vectorofargs... ; dictofargs...).