Else assert statement
Often, I know that a variable should have one of a set of values, and I want to determine which one, with an if/elif/else clause. This looks something like this: ``` if foo == 1: # do a elif foo == 2: # do b elif foo == 3: # do c else: raise ValueError('foo must be 1, 2 or 3') ``` Sometimes, I just do ``` if foo == 1: # do a elif foo == 2: # do b else: # do c ``` But this is less readable and allows errors to slip past. My proposal is to allow the following syntax: ``` if foo == 1: # do a elif foo == 2: # do b else foo == 3: # do c ``` Or perhaps the more readable version: ``` if foo == 1: # do a elif foo == 2: # do b else assert foo == 3: # do c ``` Both of these options are backward compatible, since currently nothing is allowed between the `else` and the `:`. This would be roughly equivalent to ``` if foo == 1: # do a elif foo == 2: # do b else: assert foo == 3 # do c ``` But shorter and more readable, since it puts the assertion at the same levels as the others. Thoughts?
Assertions aren't guaranteed to be executed and thus should never be used where raising an error is required. `else: raise SomeError('reason')` already has the desired effect, and it's plenty readable. On Thu, Jul 2, 2020, 7:46 PM Artemis <hollyshort21@gmail.com> wrote:
Often, I know that a variable should have one of a set of values, and I want to determine which one, with an if/elif/else clause. This looks something like this: ``` if foo == 1: # do a elif foo == 2: # do b elif foo == 3: # do c else: raise ValueError('foo must be 1, 2 or 3') ``` Sometimes, I just do ``` if foo == 1: # do a elif foo == 2: # do b else: # do c ``` But this is less readable and allows errors to slip past. My proposal is to allow the following syntax: ``` if foo == 1: # do a elif foo == 2: # do b else foo == 3: # do c ``` Or perhaps the more readable version: ``` if foo == 1: # do a elif foo == 2: # do b else assert foo == 3: # do c ``` Both of these options are backward compatible, since currently nothing is allowed between the `else` and the `:`. This would be roughly equivalent to ``` if foo == 1: # do a elif foo == 2: # do b else: assert foo == 3 # do c ``` But shorter and more readable, since it puts the assertion at the same levels as the others. Thoughts? _______________________________________________ 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/ZKAQK7... Code of Conduct: http://python.org/psf/codeofconduct/
To be more specific, if the last `elif` condition permits all remaining permissible conditions (which I suppose would just be whatever is asserted by the proposed syntax), then the else block can just be the raising of the exception. On Thu, Jul 2, 2020, 7:52 PM Steele Farnsworth <swfarnsworth@gmail.com> wrote:
Assertions aren't guaranteed to be executed and thus should never be used where raising an error is required.
`else: raise SomeError('reason')` already has the desired effect, and it's plenty readable.
On Thu, Jul 2, 2020, 7:46 PM Artemis <hollyshort21@gmail.com> wrote:
Often, I know that a variable should have one of a set of values, and I want to determine which one, with an if/elif/else clause. This looks something like this: ``` if foo == 1: # do a elif foo == 2: # do b elif foo == 3: # do c else: raise ValueError('foo must be 1, 2 or 3') ``` Sometimes, I just do ``` if foo == 1: # do a elif foo == 2: # do b else: # do c ``` But this is less readable and allows errors to slip past. My proposal is to allow the following syntax: ``` if foo == 1: # do a elif foo == 2: # do b else foo == 3: # do c ``` Or perhaps the more readable version: ``` if foo == 1: # do a elif foo == 2: # do b else assert foo == 3: # do c ``` Both of these options are backward compatible, since currently nothing is allowed between the `else` and the `:`. This would be roughly equivalent to ``` if foo == 1: # do a elif foo == 2: # do b else: assert foo == 3 # do c ``` But shorter and more readable, since it puts the assertion at the same levels as the others. Thoughts? _______________________________________________ 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/ZKAQK7... Code of Conduct: http://python.org/psf/codeofconduct/
Assertions aren't guaranteed to be executed and thus should never be used where raising an error is required.
`else: raise SomeError('reason')` already has the desired effect, and it's
Hence *roughly* equivalent to. Perhaps for this reason the second version would be confusing and should not be used. plenty readable. If this is what people think then I don't have a problem with that and there is no need for change.
Often, I know that a variable should have one of a set of values, and I want to determine which one, with an if/elif/else clause. This looks something like this: ``` if foo == 1: # do a elif foo == 2: # do b elif foo == 3: # do c else: raise ValueError('foo must be 1, 2 or 3') ``` Sometimes, I just do ``` if foo == 1: # do a elif foo == 2: # do b else: # do c ``` But this is less readable and allows errors to slip past. Quite right. :-) My proposal is to allow the following syntax: ``` if foo == 1: # do a elif foo == 2: # do b else foo == 3: # do c ``` Objection 1: "else foo==3:" is too similar to "else: foo==3" and "else: foo=3" which are already legal syntax. Objection 2: Code maintenance. Suppose you wanted to add an extra case where foo was 4. You would either have to put the "foo==4" case before the "foo==3" case, which might be undesirable for stylistic reasons, or you would have to *change* "else foo==3:" to "elif foo==3:", and then add "else foo==4:" Summary: You'd be better off writing it in the first place as per your code snippet, which is nice, simple, straightforward and easy for someone reading it to understand.
On 03/07/2020 00:39, Artemis wrote: then if you want to add an extra case, you can just insert the code for it in the obvious way. Admittedly in this example you'd also want to change the error message to 'foo must be 1, 2, 3 or 4' but if you look at the code, this is kinda obvious (and if you forget to do it, it's also obvious to someone reading the code). Objection 3: Not worth forcing Python users to learn a new construct for not much benefit.
Or perhaps the more readable version: ``` if foo == 1: # do a elif foo == 2: # do b else assert foo == 3: # do c ``` Both of these options are backward compatible, since currently nothing is allowed between the `else` and the `:`. This would be roughly equivalent to ``` if foo == 1: # do a elif foo == 2: # do b else: assert foo == 3 # do c ``` But shorter and more readable, since it puts the assertion at the same levels as the others. Thoughts? _______________________________________________ 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/ZKAQK7... Code of Conduct: http://python.org/psf/codeofconduct/
An alternative way of doing what you need that doesn't add any syntax, is more readable, runs faster, scales better and has long been used as the reason that python doesn't need a case statement would be: # Dictionary of which actions to take for foo foo_action_dict = { 'a':a, 'b':b, 'c':c, } def foo_default_handler(): """ Handler for remaining cases of foo """ print("Input value must be one of", foo_action_dict.keys()) # Call the appropriate action for foo: action_dict.get(foo, foo_default_handler)() [Steve Barnes]
-1. Assertions are ignored when Python is run with -O, so we definitely don't want to encourage relying on asserts to ensure users pass the correct value. But even if that wasn't an issue, I consider the `else: ValueError()` to be significantly more readable. Otherwise, the alternative offered by Steve Barnes of using a dict for the input options works well when you have a large number of possible inputs with entirely different behaviors. Although I'd say for anything with around 5 or less options, the `else: ValueError()` makes more sense for its simplicity. On Thu, Jul 2, 2020 at 7:43 PM Artemis <hollyshort21@gmail.com> wrote:
Often, I know that a variable should have one of a set of values, and I want to determine which one, with an if/elif/else clause. This looks something like this: ``` if foo == 1: # do a elif foo == 2: # do b elif foo == 3: # do c else: raise ValueError('foo must be 1, 2 or 3') ``` Sometimes, I just do ``` if foo == 1: # do a elif foo == 2: # do b else: # do c ``` But this is less readable and allows errors to slip past. My proposal is to allow the following syntax: ``` if foo == 1: # do a elif foo == 2: # do b else foo == 3: # do c ``` Or perhaps the more readable version: ``` if foo == 1: # do a elif foo == 2: # do b else assert foo == 3: # do c ``` Both of these options are backward compatible, since currently nothing is allowed between the `else` and the `:`. This would be roughly equivalent to ``` if foo == 1: # do a elif foo == 2: # do b else: assert foo == 3 # do c ``` But shorter and more readable, since it puts the assertion at the same levels as the others. Thoughts? _______________________________________________ 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/ZKAQK7... Code of Conduct: http://python.org/psf/codeofconduct/
participants (5)
-
Artemis
-
Kyle Stanley
-
Rob Cliffe
-
Steele Farnsworth
-
Steve Barnes