I made kwargs unpacker function for myself. I dont know if it’s applicable for all occasions, but you can take a look and see if you can use it or edit it to your liking.
Explanation:
the method_list_difference(instance) function gets the class type of the instance containing the function(that is the paramater).
Then it gets the method list of that class type object (eg. Node) and compares it to a method list of the instance.
This is to filter non-user created methods from the class type methods eg. Node.get_object() etc.
array_difference() function returns the methods that are in the instance method list, but are not in the class type method list. The difference between two arrays.
The unpack_kwargs() function gets the user defined methods listed from the method_list_difference() function.
It creates an args array the size of the amount of parameters the function(that is going to get the kwargs) (all array elements are null after the new size is created). It then replaces the last amount of the args array with default_parameter values, if there are any, so all the no_default params are null values in the args array, while the default_params has their default values. eg. [null, null, default_value1, default_value2]
Then it overwrites the args array values, at the correct function parameter index, with any matches with the kwargs you passed to the unpack_kwargs(kwargs) function.
The test function gets run with Callable(self, function_name).callv(args), where args are the unpacked_kwargs array with the paramater arguments.
I hope this helps someone.
The args array (unpacked from kwargs) / output from the below code will be null, “default_one” and “NEW param_two” respectively.
func _ready():
## calls test_func
var function_name = "test_func"
var user_defined_methods = method_list_difference(self)
##"kwargs": {"param name": "argument"}}
var kwargs = {"param_two": "NEW param_two"}
var args = unpack_kwargs(user_defined_methods, function_name, kwargs)
Callable(self, function_name).callv(args)
func test_func(no_default_param, param_one="default_one", param_two="default_two"):
print(param_one)
print(param_two)
##no_default_paramaters are null so can be used like this. just uncomment it to see
#if not no_default_param:
#no_default_param = "get some dynamic variable or something"
print(no_default_param)
func array_difference(arr1_with_difference, arr2):
var only_in_arr1 = []
for v in arr1_with_difference:
if not (v in arr2):
only_in_arr1.append(v)
return only_in_arr1
func method_list_difference(instance):
var object_method_list = ClassDB.class_get_method_list(instance.get_class())
var instance_method_list = instance.get_method_list() # includes methods from inherited custom classes
var difference_method_list = array_difference(instance_method_list, object_method_list)
return difference_method_list
func unpack_kwargs(instance_methods, method_name, kwargs) -> Array:
var args = []
for method in instance_methods:
if method.name == method_name:
# you get nulls [null, default_param_value] with default_args at the end, if any dynamic/non-default parameters exist (null)
args.resize(method.args.size() - method.default_args.size()) # creates null array elements to fill chosen array size
args.append_array(method.default_args)
for param in method.args:
if kwargs.has(param.name):
var param_index = method.args.find(param)
args[param_index] = kwargs[param.name]
return args