Apply Mark's latest changes to PEP 505
This commit is contained in:
parent
0bc5287a60
commit
23a9ad5cc1
81
pep-0505.txt
81
pep-0505.txt
|
@ -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.)
|
||||
|
||||
|
|
Loading…
Reference in New Issue