Apply Mark's latest changes to PEP 505

This commit is contained in:
Chris Angelico 2015-10-28 03:59:43 +11:00
parent 0bc5287a60
commit 23a9ad5cc1
1 changed files with 47 additions and 34 deletions

View File

@ -229,12 +229,16 @@ For inexperienced developers, the problem is worse. The top Google hit for
<http://stackoverflow.com/questions/4978738/is-there-a-python-equivalent-of-
the-c-sharp-null-coalescing-operator>`_, 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 <http://stackoverflow.com/questions/13710631/is-
there-shorthand-for-returning-a -default-value-if-none-in-python>`_ 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 "<stdin>", line 1, in <module>
File "<stdin>", 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.)