def fn(s, n=>len(s)):
"=>" just kind of bugs me, for some reason. (I love me some bikeshedding.)Of the alternatives they offer, ":=" kind of looks nicest to me:
def fn(s, n:=len(s)):
Though it doesn't really line up with the semantics of the existing walrus operator. Also, as the PEP mentions, it could look confusing when mixed with type annotations.Semantically, the "?=" alternative might be best, since it kind of makes it clear it's a default, and doesn't conflict with anything else in the language:
def fn(s, n?=len(s)):
Kind of reads like "present? else = ...".edit: At this point I'd shift from "might be best" to "almost certainly is best". I'm now a zealous "?=" advocate.
`x ?= default` is perfect IMHO. There's already prior art (Makefiles) that this means exactly "present? else = ..." with lazy evaluation of RHS expression.
It also would allow eliminating the "if x is SENTINEL" pattern, where None is a valid non-default argument.
The only potential downside is that standard, function definition-time default arguments also imply "present? else = ...". But I think of all the options available, this one makes the most sense.
def foo(..., cache={}):
...
to implement cached functions, or functions which need an internal cache for whatever reason. Later versions of Python provide an lru cache decorator, but that doesn't help with the internal cache and can be inefficient when you don't want your cache to forget any results.I'm not sure it handles the use case op is talking about.
IE def foo(bar=list()): # this creates a mutable list shard by all calls of the function. Very unlikely something you want.
Maybe the pep would allow for def foo(bar=>list()):
But the pep does not address this use case at all
>Function parameters can have default values which are calculated during function definition and saved. This proposal introduces a new form of argument default, defined by an expression to be evaluated at function call time.