The approach that I’m using right now is to make the function name communicate what the arguments are. Examples:
def add_item_to_stack(item, stack):
This way you know what the arguments are without looking at the docstring, documentation, function code or even the full function signature. The function name solely tells you what to pass as arguments. E.g. “add_item_to_stack” tells you that the first arg is the item and the second arg is the stack.
If I can’t communicate all the arguments by the function name, I will make them keyword-only like this:
def add_item_to_stack(item, stack, *, use_cache)
This way the function call will look like this:
add_item_to_stack(my_item, my_stack, use_cache=True)
And again you don’t have to look at anything except the function call to find out what the arguments are. If the last argument wasn’t keyword-only, you might end up with this:
add_item_to_stack(my_item, my_stack, True)
And the person reading this code will have no idea what the last argument is for.
Although you can guess that the metal_sword is the weapon that will be used for the attack, it’s harder to know what player1 is. Is it the enemy? Is it the player who will be attacking the enemy? We don’t know.
As it often happens, explicit code becomes verbose. Not only I have to give my functions longer names, I also often see this structure in my code:
add_item_to_stack( my_item, my_stack, use_cache=use_cache, use_thread=use_thread )
As you can see, there’s a repetition. The last two variables are named the same both in the caller’s context and inside the function. If the arguments were not keyword-only, this particular piece of code would be perfectly readable:
add_item_to_stack( my_item, my_stack, use_cache, use_thread )
The meaning of the arguments are communicated by the variables names. We understand what “use_cache” and “use_thread” are for. However, this way we give the responsibility of making the function call readable to the person who’s writing this function call, whereas it seems more right to enforce the readability when writing the function definition.
What do you think of this approach?
If my approach is good, how do I solve the problem that I described?