On Thu, Oct 31, 2019 at 02:47:35PM +0100, Andrew Barnert wrote: > On Oct 31, 2019, at 13:56, Steven D'Aprano <st...@pearwood.info> wrote: > > > > I disagree. I think it's a pretty small breaking change, > > From my test earlier on the thread, using a function to raise makes a > function that does nothing but raise and handle an exception take more > than twice as long. Which implies that the actual raise part (not > counting the outer function call, handling the exception, and > returning) is far more than twice as long.
I don't recall seeing your test code, but I don't follow your reasoning here. Unless you are using a custom Python build where the raise statement has been replaced by a raise function, I don't see how you can conclude that the raise statement inside a function takes "far more than twice as long" as a bare raise statement. Making raise a function will add the overhead of a function call, which by my tests is smaller than the cost of a raise and catch: $ ./python -m timeit "try: raise ValueError > except ValueError: pass" 100000 loops, best of 5: 3.26 usec per loop $ ./python -m timeit -s "def throw(): raise ValueError" "try: throw() > except ValueError: pass" 50000 loops, best of 5: 5.44 usec per loop YMMV. So on my machine, raise-in-a-function is about 70% slower than raise, not 100% or more. That's a pure-Python function. It's possible that a builtin function in C will have less overhead. But to paraphrase the prevailing opinion expressed in the "word list" thread, you cannot possibly be seriously worried about a few micro- seconds difference. (Only slightly serious.) In this case, I'm not that worried about micro-benchmarks unless they can be shown to add up to a significant performance degradation in macro-benchmarks too. The cost of catching exceptions is, as I understand it, quite a bit more expensive than actually throwing them. We can't throw lots of exceptions without a corresponding catch, so I expect that any additional overhead from a function call will probably be lost in the noise of the catch. But if that's not the case, then "performance" may end up being a good reason to reject this proposal. > Also, there are many places in the Python data model where you have to > raise an exception, such as StopIteration; Does the Python data model not have function calls? *wink* > And what’s the advantage? > > If we need raise inside an expression without extra overhead, this > doesn’t solve the problem; we’d need a raise expression (similar to > the yield expression), not a raise function. Yield expressions are a red herring here. Yield expressions are a weird syntactic form that allow you to feed data into a running generator. raise doesn't need to do that. The raise function will never return, so it doesn't need to return a value. It will be kind of like os._exit, and sys.exit. > If we don’t care about the overhead, there is no problem to solve; you > can already get this behavior with a one-liner. If that’s still too > inconvenient or undiscoverable, we can add the one-liner to builtins > without removing the statement at the same time. So, what’s the > benefit of removing the statement? "Only One Way To Do It" *wink* We could have added a print_ function and kept the print statement too. And for years, people wrote their own one-liner print_ functions. (I have lost count of the number of times I did.) If your argument was compelling, we never would have changed print and exec to functions. But we did. The "just use a one-liner" argument isn't very strong. It's a work-around for the missing functionality, not a positive argument in favour of the status quo. If, back in the early days of Python, Guido had made raise a function, we'd all accept it as normal and desirable. I doubt anyone would say "I really wish it was impossible to call raise from an expression without having to write an unnecessary boilerplate wrapper function". As I said above, I'll grant you the *possibility* that performance may tilt the balance, but honestly, I see no other reason why we should prefer a *less flexible, less useful* raise statement over a more flexible, more useful function. Especially if a built-in function written in C can avoid most of the pure-Python function call overhead, narrowing the performance gap. -- Steven _______________________________________________ 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/AJTPDZTODJW34VYCRDEXHUMSG4BYMCQ2/ Code of Conduct: http://python.org/psf/codeofconduct/