From 23a9ad5cc1e018637cfe7bdc4a1bd826f2b34e09 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Wed, 28 Oct 2015 03:59:43 +1100 Subject: [PATCH] Apply Mark's latest changes to PEP 505 --- pep-0505.txt | 81 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/pep-0505.txt b/pep-0505.txt index fa3a25dd3..adc68cf5b 100644 --- a/pep-0505.txt +++ b/pep-0505.txt @@ -229,12 +229,16 @@ For inexperienced developers, the problem is worse. The top Google hit for `_, and the top answer says to use ``or``. The top answer goes on to explain the caveats of using ``or`` like this, but how -many beginning developers go on to read all those caveats? +many beginning developers go on to read all those caveats? The accepted answer +on `a more recent question `_ says to use +``or`` without any caveats at all. These two questions have a combined 26,000 +views! The common usage of ``or`` for the purpose of providing default values is undeniable, and yet it is also booby-trapped for unsuspecting newcomers. This suggests that a safe operator for providing default values would have positive -utility. While some critics claim that ``None-aware`` operators will be abused +utility. While some critics claim that ``None``-aware operators will be abused for error handling, they are no more prone to abuse than ``or`` is. @@ -773,36 +777,44 @@ Note in the last example that ``time.sleep(10)`` represents an expensive function call, e.g. initializing a complex data structure. In this example ``time.sleep`` is not evaluated, and the result ``300`` is returned instantly. -The operator has precedence lower than ``not`` but higher than ``and`` and -``or``. This precedence makes reasoning about the order of operations -comfortable, because it has precedence similar to the operators used for -coalescing false-y values. Here are pairs of examples, where each item in the -pair is evaluated identically to the other item in the pair:: +The operator has higher precedence than the comparison operators ``==``, ``>``, +``is``, etc., but lower precedence than any bitwise or arithmetic operators. +This precedence is chosen for making "default value" expressions intuitive to +read and write:: - >>> not None ✊🍆 False - True - >>> (not None) ✊🍆 False + >>> user_flag = None + >>> default_flag = True + >>> not user_flag ✊🍆 default_flag # Same as next expression. + False + >>> not (user_flag ✊🍆 default_flag) # Same as previous. + False + >>> (not user_flag) ✊🍆 default_flag # Different from previous. True - >>> 'foo' in dict() ✊🍆 {'foo': 'bar'} - False - >>> ('foo' in dict()) ✊🍆 {'foo': 'bar'} + >>> user_quantity = None + >>> default_quantity = 1 + >>> 1 == user_quantity ✊🍆 default_quantity # Same as next expression. + True + >>> 1 == (user_quantity ✊🍆 default_quantity) # Same as previous. + True + >>> (1 == user_quantity) ✊🍆 default_quantity # Different from previous. False - >>> 1 == None ✊🍆 1 - False - >>> (1 == None) ✊🍆 1 - False - -But ``and`` and ``or`` have lower precedence:: - - >>> 2 or None ✊🍆 err() + >>> user_words = None + >>> default_words = ['foo', 'bar'] + >>> 'foo' in user_words ✊🍆 default_words # Same as next expression. + True + >>> 'foo' in (user_words ✊🍆 default_words) # Same as previous. + True + >>> ('foo' in user_words) ✊🍆 default_words # Different from previous. Traceback (most recent call last): File "", line 1, in - File "", line 1, in err - Exception: foo - >>> (2 or None) ✊🍆 err() - 2 + TypeError: argument of type 'NoneType' is not iterable + + >>> user_discount = None + >>> default_discount = 0.9 + >>> price = 100 + >>> price * user_discount ✊🍆 default_discount Recall the example above of calculating the cost of items in a shopping cart, and the easy-to-miss bug. This type of bug is not possible with the ``None``- @@ -840,9 +852,8 @@ preserving the short circuit semantics of the code that it replaces. -------------------------- The idea of a ``None``-aware function invocation syntax was discussed on python- -ideas, but the idea was rejected by BDFL. The reasons for this rejection are -detailed above. - +ideas. The idea was not popular, so no such operator is included in this +proposal. (Justification for its exclusion is discussed in a previous section.) Still, calling a function when it is not ``None`` is a common idiom in Python, particularly for callback functions. Consider this hypothetical example:: @@ -865,10 +876,11 @@ written more concisely as:: Instead, consider a "``None``-severing" operator, however, which is a short- circuiting, boolean operator similar to the ``None``-coalesing operator, except -it returns its left operand if that operand is None and otherwise returns the -right operand. If the left operand is None, then the right operand is not -evaluated. Let's temporarily spell this operator ``✂`` and rewrite the example -accordingly:: +it returns ``None`` if the left operand is ``None`` and returns the right +operand otherwise. It has short circuiting behavior that compliments the +``None``-coalescing operator: if the left operand is None, then the right +operand is not evaluated. Let's temporarily spell this operator ``✂`` and +rewrite the example accordingly:: import time @@ -1153,7 +1165,7 @@ operator. 2. ``foo or? bar or? baz`` - Pros: similar to existing ``or`` operator - Cons: the difference between this and ``or`` is not intuitive; punctuation - is ugly + is ugly; different precedence from ``or`` may be confusing 3. ``foo ? bar ? baz`` - Pros: similar to ``??`` used in other languages - Cons: punctuation is ugly; possible conflict with IPython; not used by any @@ -1189,7 +1201,8 @@ the ``None``- coalescing operator. 2. ``foo and? bar`` - Pros: symmetric with ``or?`` - Cons: punctuation is ugly; possible conflict with IPython; difficult to - google to find out what it means + google to find out what it means; different precedence from ``and`` may be + confusing 3. No ``None``-severing operator. - (Pros and cons discussed throughout this document.)