> Your magic template has apparently turned positional-or-keyword parameters into keyword-only. This means that every exception class that you’d normally construct with positional args today (which apparently includes even your example, since that’s what you did in version 1 and 2) now requires keyword boilerplate on every line where you construct one. And, since you generally construct and use a class many times, but only define it once, that’s adding a lot more boilerplate than it’s saving.
In my mind, you're filling in a format string, so of course you're going to give the values by name. But I can see how that would seem like a step backwards compared to an exception with positional arguments. And yes, taking arguments in the order they appear in the string is too much magic and not intuitive. > Also, even in the definition, while you are saving one line, you’re doing it by replacing a standard idiom used all over Python that has an obvious meaning, which nobody ever forgets how to write, with magic involving a special name that’s unlike anything else in the stdlib, which many people will forget how to write, forcing them to look up the docs or find an example whenever they add the first new exception to a new module. That seems overly pessimistic. If you can remember to extend a class, it's not too much of a stretch to remember what aspect of it that you're defining. > Also, this doesn’t fill in the exception’s stored args. Is there a way to fix that without requiring more boilerplate? Remember, stored args are positional, not keywords. So, even if you can come up with some magic (e.g., parsing the format string to sort the keywords in the order of first appearance), that only helps the interpreter, not a human reader who sees exc.args[2] in an except clause for an exception created with three keyword args and has to guess which one is #2. Without explicitly listing the args in order somewhere, how do you solve that? And is there a way to list the named args of a function in order that’s less boilerplate than (but just as understandable as) a def statement? I don't see why you would want to access arguments by their position. Why wouldn't you access them by name? ie: exc.action The user-defined exceptions in the Python documentation don't pass arguments to the base class either: https://docs.python.org/3/tutorial/errors.html#user-defined-exceptions So let's go ahead and assume my implementation is flawed. The fact that people prefer to copy their format strings all over their projects implies that the current exception scheme is suboptimal. Can we agree on that? If not, there's no need to continue this discussion. On Thu, Aug 8, 2019 at 4:12 PM Andrew Barnert <abarn...@yahoo.com> wrote: > On Aug 8, 2019, at 08:52, Ryan Fox <r...@rcfox.ca> wrote: > > > > >>> class MyException(Exception): > > ... def __init__(self, action, context): > > ... super().__init__(f'Bad thing happened during {action} in > {context}') > > >>> raise MyException(current_action, current_context) > > ... > > > Version 2 looks simple enough to do, but all of the repetitious > boilerplate adds up when several exception types need to be defined. (And > it's even worse when you want all of your code to include typing > annotations.) Most people don't bother. > > > > My proposal is a new exception class as the preferred base for > user-defined exceptions: > > > > >>> class MyException(ExceptionTemplate): > > ... message = 'Bad thing happened during {action} in {context}' > > >>> raise MyException(action=current_action, context=current_context) > > Does this really save boilerplate? > > Your magic template has apparently turned positional-or-keyword parameters > into keyword-only. This means that every exception class that you’d > normally construct with positional args today (which apparently includes > even your example, since that’s what you did in version 1 and 2) now > requires keyword boilerplate on every line where you construct one. And, > since you generally construct and use a class many times, but only define > it once, that’s adding a lot more boilerplate than it’s saving. > > Also, even in the definition, while you are saving one line, you’re doing > it by replacing a standard idiom used all over Python that has an obvious > meaning, which nobody ever forgets how to write, with magic involving a > special name that’s unlike anything else in the stdlib, which many people > will forget how to write, forcing them to look up the docs or find an > example whenever they add the first new exception to a new module. > > Also, this doesn’t fill in the exception’s stored args. Is there a way to > fix that without requiring more boilerplate? Remember, stored args are > positional, not keywords. So, even if you can come up with some magic > (e.g., parsing the format string to sort the keywords in the order of first > appearance), that only helps the interpreter, not a human reader who sees > exc.args[2] in an except clause for an exception created with three keyword > args and has to guess which one is #2. Without explicitly listing the args > in order somewhere, how do you solve that? And is there a way to list the > named args of a function in order that’s less boilerplate than (but just as > understandable as) a def statement? > > >
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/7R7OHZ5N7GZ3H77OOJMUXQTOMRY2BBFY/ Code of Conduct: http://python.org/psf/codeofconduct/