On Sun, May 24, 2020 at 10:05 PM Dominik Vilsmeier <dominik.vilsmeier@gmx.de> 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) # [], {}
This still leaves the information out of the signature, which I've argued is a more important consideration than saving a couple of lines of boilerplate. You could solve this by allowing people to write: ``` @supply_defaults(x=list, y=dict) def bar(x=[], y={}): print(x, y) # [], {} ``` and telling `supply_defaults` to ignore the actual defaults wherever factories are supplied, but there's no guarantee people will put sensible defaults in the signature. For the mutable defaults only case, you could have: ``` @copy_mutable_defaults def bar(x=[], y={}): print(x, y) # [], {} ``` which would only pay attention to a specific whitelist of default types like list, dict, and set, and copy them each time. Not great.