PEP 572: Is it a good ideas that walrus operator can be used in assertions since it causes side effects?
Hi, Recently the idea has come to me that walrus operator can have some issues when use in assertions. I have been taught that assertions must not produce side effects at all. This is a problem in languages such as C. But not in Python (until 3.8) since it does not allow assignment expressions. But now, for best or worst, we have the walrus operator and a code like this is possible: `python3.8 -c "assert (always := True); print(f'{always=}')"` Which outputs: ``` always=True ``` since the assertion is always true. However, if assertions are disabled: `python3.8 -Oc "assert (always := True); print(f'{always=}')"` it raises an exception: ``` Traceback (most recent call last): File "<string>", line 1, in <module> NameError: name 'always' is not defined ``` because of the side effect caused by the walrus operator. Do not you think that disabling walrus operators in assertions would be a good idea? Would be it possible? Personally, I do not see many advantages in walrus operator (versus disadvantages, of course). However, in the case of assertions, a nice and secure feature of Python has been lost without any apparent benefit. Thank you.
Lua is known for using assignments in asserts in C. It can come in handy for more complex, multi-part assertions. On 2020-02-11 4:10 p.m., jdveiga@gmail.com wrote:
Hi,
Recently the idea has come to me that walrus operator can have some issues when use in assertions.
I have been taught that assertions must not produce side effects at all. This is a problem in languages such as C. But not in Python (until 3.8) since it does not allow assignment expressions. But now, for best or worst, we have the walrus operator and a code like this is possible:
`python3.8 -c "assert (always := True); print(f'{always=}')"`
Which outputs:
``` always=True ```
since the assertion is always true.
However, if assertions are disabled:
`python3.8 -Oc "assert (always := True); print(f'{always=}')"`
it raises an exception:
``` Traceback (most recent call last): File "<string>", line 1, in <module> NameError: name 'always' is not defined
```
because of the side effect caused by the walrus operator.
Do not you think that disabling walrus operators in assertions would be a good idea? Would be it possible?
Personally, I do not see many advantages in walrus operator (versus disadvantages, of course). However, in the case of assertions, a nice and secure feature of Python has been lost without any apparent benefit.
Thank you. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/KJFG76... Code of Conduct: http://python.org/psf/codeofconduct/
Sorry, Soni, I do no speak Lua. Can you provide any documentation on that point? I have found a function called assert but I am not sure that it works like assertions in Python.
I should perhaps provide a link to the relevant discussion in the Lua mailing list. For what it's worth, you'll only be looking at C. https://marc.info/?l=lua-l&m=157312955532763&w=2 On 2020-02-11 4:55 p.m., jdveiga@gmail.com wrote:
Sorry, Soni, I do no speak Lua. Can you provide any documentation on that point? I have found a function called assert but I am not sure that it works like assertions in Python. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/A3CYE6... Code of Conduct: http://python.org/psf/codeofconduct/
Yes = The Walrus operator, poorly used, can caused the problem in the OP, and many, many others. It does not make a difference - we discussed and got to the conclusion that the benefits of having it surpass whatever bad uses people put it for. It clearly does not make sense to try to modify the syntax to forbid "walrus containing expressions inside assert statements", as even the creation of a variable inside a conditional `if` block could have the same effect you are describing, when the code is broken. On Tue, 11 Feb 2020 at 17:22, Soni L. <fakedme+py@gmail.com> wrote:
I should perhaps provide a link to the relevant discussion in the Lua mailing list. For what it's worth, you'll only be looking at C.
https://marc.info/?l=lua-l&m=157312955532763&w=2
Sorry, Soni, I do no speak Lua. Can you provide any documentation on
On 2020-02-11 4:55 p.m., jdveiga@gmail.com wrote: that point? I have found a function called assert but I am not sure that it works like assertions in Python.
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/A3CYE6... Code of Conduct: http://python.org/psf/codeofconduct/
Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/H3VTCE... Code of Conduct: http://python.org/psf/codeofconduct/
However, in the case of assertions, a nice and secure feature of Python has been lost without any apparent benefit.
It's always been possible to have side effects from an assertion:
always Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'always' is not defined def f(): ... global always ... always = True ... return True ... assert f() always True
The walrus operator just adds another way to do it.
Good point, Brandt. However, `global` is not used in the assertion itself as walrus operator can be. My point is: is it good to add a new way of causing side effects in assertions? Thank you.
On Wed, Feb 12, 2020 at 6:51 AM <jdveiga@gmail.com> wrote:
Good point, Brandt. However, `global` is not used in the assertion itself as walrus operator can be.
My point is: is it good to add a new way of causing side effects in assertions?
My point is: Is it good to find extremely stupid things that can be done with a code construct, and then blaming the code construct? I can do way, WAY worse with assertions. assert globals().__setitem__("len", lambda x: 5) is None Obviously lambda is evil, because it can be used in this way. This thread doesn't belong on python-ideas, and I don't see a lot of value moving it to python-list either. Maybe it can move to Google Groups instead? ChrisA
On 02/11/2020 11:49 AM, jdveiga@gmail.com wrote:
My point is: is it good to add a new way of causing side effects in assertions?
Good or not, it's not changing now. It's probably safe to say that every new language feature adds one more way to break assertions. It is our responsibility to have correct code. -- ~Ethan~
On Tue, Feb 11, 2020 at 07:10:18PM -0000, jdveiga@gmail.com wrote:
I have been taught that assertions must not produce side effects at all.
That's good practice, but saying that they "must not" is too strong. The risk here is not the side-effect, but relying on that side-effect (which may be disabled) outside of the assertion. Some side-effects are perfectly fine: assert log(message) or condition
This is a problem in languages such as C. But not in Python (until 3.8) since it does not allow assignment expressions.
Assignment is not the only possible side-effect. These have been possible back to Python 2.4 and probably older: assert mylist.pop() assert globals().update({'flag': expression}) or flag assert delattr(mymodule, 'spam') or condition In Python 3, we can also do things like this: assert print(message) or condition assert exec("value = expression") or condition Since assertions can call functions (and methods), and functions can have side-effects, Python has *always* been able to have side-effects inside assertions.
But now, for best or worst, we have the walrus operator
Oh, definitely for the best. This now allows us to write complex assertions much more easily and efficiently: assert log(flag := complex_expression) or flag Previously we would have to write this: if __debug__: flag = complex_expression assert flag which is much less convenient, but is another way to get side-effects in an assertion.
However, if assertions are disabled:
`python3.8 -Oc "assert (always := True); print(f'{always=}')"`
it raises an exception:
Indeed. So does this: [steve@ando ~]$ python -c "if False: always = 999 print(always)" Traceback (most recent call last): File "<string>", line 3, in <module> NameError: name 'always' is not defined and for roughly the same reason. [...]
Do not you think that disabling walrus operators in assertions would be a good idea?
No. -- Steven
On 02/11/2020 01:49 PM, Steven D'Aprano wrote:
Oh, definitely for the best. This now allows us to write complex assertions much more easily and efficiently:
assert log(flag := complex_expression) or flag
That doesn't seem very useful: for that assert to fail, `flag` would have to be falsey, and if falsey, then surely the log of it is not helpful? -- ~Ethan~
assert log(flag := complex_expression) or flag
That doesn't seem very useful: for that assert to fail, `flag` would have to be falsey, and if falsey, then surely the log of it is not helpful?
Unless complex_expression produces an object that has useful information when Falsey. But it’s a toy example that I think makes the point well that there may be a good use of := in an assert. In fact, it’s my impression (and we’ll see how it works out) that the walrus operator is best used in a “local” manner such as this— if the assignment is important later in the code, it may be better to stick with regular assignment anyway. -CHB
-- ~Ethan~ _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/N5BMTK... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
On Thu, Feb 13, 2020 at 1:50 AM Ethan Furman <ethan@stoneleaf.us> wrote:
On 02/11/2020 01:49 PM, Steven D'Aprano wrote:
Oh, definitely for the best. This now allows us to write complex assertions much more easily and efficiently:
assert log(flag := complex_expression) or flag
That doesn't seem very useful: for that assert to fail, `flag` would have to be falsey, and if falsey, then surely the log of it is not helpful?
Maybe the logging is meant to be useful when the flag is truthy. If the assertion fails, it's an immediate error, but if it passes, you get an informational log that might help interpret future messages? ChrisA
On Feb 12, 2020, at 06:49, Ethan Furman <ethan@stoneleaf.us> wrote:
On 02/11/2020 01:49 PM, Steven D'Aprano wrote:
Oh, definitely for the best. This now allows us to write complex assertions much more easily and efficiently: assert log(flag := complex_expression) or flag
That doesn't seem very useful: for that assert to fail, `flag` would have to be falsey, and if falsey, then surely the log of it is not helpful?
You’ve never had some rare code path that’s missing a return, and wasted half an hour trying to figure out how you could possibly be getting 0 out of that calculation before realizing you’re actually getting None?
On 02/12/2020 10:00 AM, Andrew Barnert wrote:
On Feb 12, 2020, at 06:49, Ethan Furman <ethan@stoneleaf.us> wrote:
On 02/11/2020 01:49 PM, Steven D'Aprano wrote:
Oh, definitely for the best. This now allows us to write complex assertions much more easily and efficiently: assert log(flag := complex_expression) or flag
That doesn't seem very useful: for that assert to fail, `flag` would have to be falsey, and if falsey, then surely the log of it is not helpful?
You’ve never had some rare code path that’s missing a return, and wasted half an hour trying to figure out how you could possibly be getting 0 out of that calculation before realizing you’re actually getting None?
*sheepish grin* Point taken. -- ~Ethan~
Thank you for all your answers. They were all very instructive to me. However, after further investigation, I feel that I have made a mistake when putting this topic on the table. When walrus operator was discussed, it was proposed to restrict assignment expressions to if, elif, and while statements. That proposal was rejected. I realised now that that also applies, by analogy, to assert statement. So, sorry for taking this issue back. My apologies. I was not my intention to re-start any superseded debate. The walrus operator, as you know, has been —and will be— highly controversial and material on this matter is enormous. Reviewing all this material is a huge task that I should have done before speaking. Sorry again and thank you.
participants (9)
-
Andrew Barnert
-
Brandt Bucher
-
Chris Angelico
-
Christopher Barker
-
Ethan Furman
-
jdveiga@gmail.com
-
Joao S. O. Bueno
-
Soni L.
-
Steven D'Aprano