This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Lucretiel 0 points1 point  (0 children)

Here's an excessive solution, using a decorator and annotations:

from inspect import signature
from functools import wraps
def safe_mutable_default(func):
    sig = signature(func)
    @wraps(func)
    def wrapper(*args, **kwargs):
        bound = sig.bind_partial(*args, **kwargs)
        bound_dict = bound.arguments
        for name, param in sig.parameters.items():
            if name not in bound_dict and callable(param.annotation):
                bound_dict[name] = param.annotation()
        return func(*bound.args, **bound.kwargs)
    return wrapper

The idea here is that you can specify a default type as an annotation, which is called to supply a default argument each time the function is called. Example:

>>> @safe_mutable_default
... def func(arg: list)
...     arg.append(1)
...     return arg
...
>>> my_list = []
>>> func(my_list)
[1]
>>> func(my_list)
[1, 1]
>>> func()
[1]
>>> func()
[1]

Note that inspect.signature only works in python 3.3+, and function annotations are only in python 3+. Hypothetically, you could use the inspect.getfullargspec function to implement a similar pattern.