I have two functions that use a decorator, the problem is one has 2 parameters while the other only has one, which of these is best solution?
matches, _ = args
matches = args
Both are brittle:
- (A) assumes that
len(args) == 2 and will raise a ValueError if this is not the case
- (B) assumes that
len(args) > 0 and will raise an IndexError if called without arguments
So, (B) is a bit more generally usable. But if none of the other arguments are used in
make_clozein, then why not change the function signature to be
This is clearer, and leaves less room for bugs to sneak in.
Otherwise, if you do use some of the other arguments later in the function (or if you have another reason for keeping the current signature), I would change it to sth like:
matches = args if args else None
The decorator passes 2 arguments
func(arg1, arg2) when calling the function which could be the one that has two parameters
foo(param1, param2) or the other that has only one
def make_clozein(matches): wouldn’t work.
Ah, so if it must recieve either one or two arguments, with the first always being the one you want and the second discarded, why not do
def make_clozein(matches, *args):
Now the first argument is always mapped to
matches, while the second, if present, is included in the
args list, otherwise it is an empty list. Since you apparently don’t actually use the second argument, you can simply ignore
args (and potentially name it something like, e.g.
However, this allows more than two arguments to be passed, so if you know you’re always going to get two and want to check for cases of >2, you could do, e.g.
def make_clozein(matches, _unused=None):
That’s a more explicit way to do it. Can a class solve this problem more efficiently? Currently I remove the decorator because I screwed up, so I’m trying to learn unit testing so it won’t happen again.
Well, not really the described problem of parsing arguments as you intend, no. But I’m guessing you might be implying this is an XY problem, and you actually are asking about a better solution to whatever underlying problem for which you created and used the decorator (e.g. doing find and replace on the arguments to multiple functions?). In that case, it certainly could be one, yeah. Or simply a regular helper function that your function calls. It all depends on what you actually want to do and why; if you could provide more details about about that, perhaps we could suggest something.
So the original problem is I have a function to find a cloze pattern and shuffle them (because the flashcard app I’m using doesn’t have a shuffle mode), but I created another function that modified the clozes, which I realize I’m just copying the first function with just a little difference.
Now I’m wondering what the decorator is really intended for.