On 25.05.20 03:03, Rob Cliffe via Python-ideas wrote:
On 24/05/2020 21:03, Dominik Vilsmeier wrote:
On 24.05.20 18:34, Alex Hall wrote:
OK, let's forget the colon. The point is just to have some kind of
'modifier' on the default value to say 'this is evaluated on each
function call', while still having something that looks like
`arg=<default>`. Maybe something like:
def func(options=from {}):
It looks like the most common use case for this is to deal with
mutable defaults, so what is needed is some way to specify a default
factory, similar to `collections.defaultdict(list)` or
`dataclasses.field(default_factory=list)`. This can be handled by a
decorator, e.g. by manually supplying the factories or perhaps
inferring them from type annotations:
@supply_defaults
def foo(x: list = None, y: dict = None):
print(x, y) # [], {}
@supply_defaults(x=list, y=dict)
def bar(x=None, y=None):
print(x, y) # [], {}
That's very clever, but if you compare it with the status quo:
def bar(x=None, y=None):
if x is None: x = []
if y is None: y={}
it doesn't save a lot of typing and will be far more obscure to newbies
who may not know about decorators.
Actually it was intended to use type annotations a la PEP 585 (using
builtin types directly) and hence not requiring explicit specification
of the factory:
@supply_defaults
def bar(x: list = None, y: dict = None):
pass
This also has the advantage that the types are visible in the function
signature. Sure this works only in a limited number of cases, but the
case of mutable defaults seems to be quite prominent, and this solves it
at little cost.
No, forget fudges.
I think what is needed is to take the bull by the horns and add some
*new syntax*
that says "this default value should be (re)calculated every time it
is needed".
Personally I don't think the walrus operator is too bad:
def bar(x:=[], y:={}):
What about using `~` instead of `:=`. As a horizontal symbol it has some
similarity to `=` and usually "~" denotes proportionality which also
allows to make a connection to the use case. For proportionality "x ~ y"
means there's a non-zero constant "k" such that "x = k*y" and in the
case of defaults it would mean, there's a non-trivial step such that `x
= step(y)` (where `step=eval` roughly).
def bar(x=1, y~[], z ~ {}):
It looks better with spaces around "~" but that's probably a matter of
being used to it.
A disadvantage is that `~` is already a unary operator, so one could do
this: `def foo(x~~y)`. But how often does this occur anyway?
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/python-ideas@python.org/message/O644JM442V5K4J5ZTJPRFTQ6YY4XMI74/
Code of Conduct: http://python.org/psf/codeofconduct/