PEP 671: Quick pass over wording and settle some things from discussion
This commit is contained in:
parent
745bfda492
commit
45cf9e5250
53
pep-0671.rst
53
pep-0671.rst
|
@ -80,29 +80,27 @@ implementations, it should be considered dubious::
|
||||||
def spaminate(sausage=>eggs + 1, eggs=>sausage - 1): # Confusing, may fail
|
def spaminate(sausage=>eggs + 1, eggs=>sausage - 1): # Confusing, may fail
|
||||||
def frob(n=>len(items), items=[]): # May fail, may succeed
|
def frob(n=>len(items), items=[]): # May fail, may succeed
|
||||||
|
|
||||||
|
Moreover, even if syntactically and semantically legal, this kind of construct
|
||||||
|
is highly confusing to other programmers, and should be avoided.
|
||||||
|
|
||||||
|
|
||||||
Choice of spelling
|
Choice of spelling
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Our chief syntax proposal is ``name=>expression`` -- our two syntax proposals
|
While this document specifies a single syntax ``name=>expression``, alternate
|
||||||
... ahem. Amongst our potential syntaxes are::
|
spellings are similarly plausible. Open for consideration are the following:
|
||||||
|
|
||||||
# Preferred options: adorn the equals sign (approximate preference order)
|
|
||||||
def bisect(a, hi=>len(a)):
|
def bisect(a, hi=>len(a)):
|
||||||
def bisect(a, hi=:len(a)):
|
|
||||||
def bisect(a, hi:=len(a)):
|
def bisect(a, hi:=len(a)):
|
||||||
def bisect(a, hi?=len(a)):
|
def bisect(a, hi?=len(a)):
|
||||||
def bisect(a, hi!=len(a)):
|
|
||||||
def bisect(a, hi=\len(a)):
|
An alternative reference implementation is under consideration, which would
|
||||||
def bisect(a, hi=@len(a)):
|
use this syntax::
|
||||||
# Less preferred option: adorn the variable name
|
|
||||||
def bisect(a, @hi=len(a)):
|
def bisect(a, @hi=len(a)):
|
||||||
# Less preferred option: adorn the expression
|
|
||||||
def bisect(a, hi=`len(a)`):
|
|
||||||
|
|
||||||
Since default arguments behave largely the same whether they're early or late
|
Since default arguments behave largely the same whether they're early or late
|
||||||
bound, the preferred syntax is very similar to the existing early-bind syntax.
|
bound, the syntax is deliberately similar to the existing early-bind syntax.
|
||||||
The alternatives offer little advantage over the preferred one.
|
|
||||||
|
|
||||||
How to Teach This
|
How to Teach This
|
||||||
=================
|
=================
|
||||||
|
@ -117,6 +115,12 @@ bound arguments are broadly equivalent to code at the top of the function::
|
||||||
def add_item(item, target=<OPTIONAL>):
|
def add_item(item, target=<OPTIONAL>):
|
||||||
if target was omitted: target = []
|
if target was omitted: target = []
|
||||||
|
|
||||||
|
A simple rule of thumb is: "target=expression" is evaluated when the function
|
||||||
|
is defined, and "target=>expression" is evaluated when the function is called.
|
||||||
|
Either way, if the argument is provided at call time, the default is ignored.
|
||||||
|
While this does not completely explain all the subtleties, it is sufficient to
|
||||||
|
cover the important distinction here (and the fact that they are similar).
|
||||||
|
|
||||||
|
|
||||||
Interaction with other open PEPs
|
Interaction with other open PEPs
|
||||||
================================
|
================================
|
||||||
|
@ -132,13 +136,15 @@ be defined by the function. Additionally, dedicated sentinel objects can be
|
||||||
used as dictionary lookup keys, where PEP 671 does not apply.
|
used as dictionary lookup keys, where PEP 671 does not apply.
|
||||||
|
|
||||||
|
|
||||||
Open Issues
|
Interaction with annotations
|
||||||
===========
|
============================
|
||||||
|
|
||||||
- Annotations go before the default, so in all syntax options, it must be
|
Annotations go before the default, so in all syntax options, it must be
|
||||||
unambiguous (both to the human and the parser) whether this is an annotation,
|
unambiguous (both to the human and the parser) whether this is an annotation,
|
||||||
a default, or both. The worst offender is the ``:=`` notation, as ``:int=``
|
a default, or both. The alternate syntax ``target:=expr`` runs the risk of
|
||||||
would be a valid annotation and early-bound default.
|
being misinterpreted as ``target:int=expr`` with the annotation omitted in
|
||||||
|
error, and may thus mask bugs. The preferred syntax ``target=>expr`` does not
|
||||||
|
have this problem.
|
||||||
|
|
||||||
|
|
||||||
Implementation details
|
Implementation details
|
||||||
|
@ -159,10 +165,13 @@ needs to be queried. If it is ``None``, then the default is indeed the value
|
||||||
``Ellipsis``; otherwise, it is a descriptive string and the true value is
|
``Ellipsis``; otherwise, it is a descriptive string and the true value is
|
||||||
calculated as the function begins.
|
calculated as the function begins.
|
||||||
|
|
||||||
When a parameter with a late-bound default is omitted, the
|
When a parameter with a late-bound default is omitted, the function will begin
|
||||||
function will begin with the parameter unbound. The function begins by testing
|
with the parameter unbound. The function begins by testing for each parameter
|
||||||
for each parameter with a late-bound default, and if unbound, evaluates the
|
with a late-bound default using a new opcode QUERY_FAST, and if unbound,
|
||||||
original expression.
|
evaluates the original expression. This opcode (available only for fast locals
|
||||||
|
and not for other types of variable) pushes True onto the stack if the given
|
||||||
|
local has a value, and False if not - meaning that it pushes False if LOAD_FAST
|
||||||
|
would raise UnboundLocalError and True if it would succeed.
|
||||||
|
|
||||||
Out-of-order variable references are permitted as long as the referent has a
|
Out-of-order variable references are permitted as long as the referent has a
|
||||||
value from an argument or early-bound default.
|
value from an argument or early-bound default.
|
||||||
|
|
Loading…
Reference in New Issue