I have a function f:
function f(; a=1, b=2, c=3)
return 1
end
I can get the names of its kwargs using:
Base.kwarg_decl.(methods(f))[1]
Is there any way to get the default values of those kwargs?
I have a function f:
function f(; a=1, b=2, c=3)
return 1
end
I can get the names of its kwargs using:
Base.kwarg_decl.(methods(f))[1]
Is there any way to get the default values of those kwargs?
I came across the same need, and wrote a function for that.
From this stackoverflow similar question, it seems that code_lowered
is the only function that holds the kwargs values, but in a confusing format if they are not “basic” types (Nothing or a custom type for example). Fortunately the values can be retrieved back!
"""
get_kwargs(func_name::Function, args_types::Tuple)
Return a NamedTuple containing each supported kwarg and its default value for a given method.
# Arguments
- `func_name` is the name of the function
- `args_types` is a tuple of argument types for the desired method
"""
function get_kwargs(func_name::Function, args_types::Tuple)
kwargs_names = Base.kwarg_decl(methods(func_name, args_types)[1])
l = length(kwargs_names)
if l==0
# no kwargs
return (;)
else
# lowered form of the method contains kwargs default values, but some are hidden
code = code_lowered(func_name, args_types)[1].code
str_code = ["$c" for c in code]
# get index corresponding to the function
index = findall(x -> occursin("$func_name", x), str_code)[1]
# get lowered value of each kwarg
values = code[index].args[2:2+l-1]
# get back the original value according to the lowered value type
kwargs_values = map(v ->
if v isa Core.SSAValue
eval(code[v.id])
elseif v isa GlobalRef
eval(v)
else
v
end
, values)
# reconstruct kwargs
NamedTuple(zip(kwargs_names, kwargs_values))
end
end
Example function to test it:
struct MyType
m::Int64
t::String
end
myfunc(x::Float64; a=2, b=nothing, c="3", d=34.2, e=MyType(2,"two")) = println("test")
Retrieving kwargs:
get_kwargs(myfunc, (Float64,))
Result:
(a = 2, b = nothing, c = "3", d = 34.2, e = MyType(2, "two"))
Fyi, CodeTracking.jl might be useful for this too:
julia> code_string(myfunc, (Float64,))
"myfunc(x::Float64; a=2, b=nothing, c=\"3\", d=34.2, e=MyType(2,\"two\")) = println(\"test\")"