I don’t know why there’s a trend of using None for the default, instead of the actual value. Unless you want to allow to monkey patch sys.stdout for instance.
Don’t you mean frozenset()? Pep 416 was rejected.
It might be a matter of performance though, as an identity check is faster than a conversion to list. But in case you already support an iterable, using a tuple as default is a no-brainer. Maybe this is something linters can help with?
A list expects an iterable, not multiple arguments.
frozendict is imported from the fozendict library frozendict · PyPI
Yes I would use frozenset too.
@dg-pb
I think getting rid of Nones would be a better improvement rather than making it easier to work with.
A lot could be improved via education.
def f(x: list|tuple = ()):
...
is already a better pattern than
def (f:x list|None = None):
...
in a myriad of ways. More readable, less boilerplate. Forces you to use good habits like not mutating function arguments.
None-aware operators sound like they would increase bad programming habits and increase silent bugs.
All that said, the pattern def f(x: list|tuple = ()) is relatively hard to discover in my experience, and not very common in code I’ve seen.
The python ecosystem would probably be significantly improved if def f(x:list ?= []) was available as an alternative, because it would reduce instances of def (f:x list|None = None), which would also reduce the need for None-aware operators.
Probably because if you are only using tuple to allow for an immutable default, then you are almost certainly only using the argument as an Iterable or a Sequence, and don’t need to specify listortuple as the argument type.
It’s only a bug if you expected "abc" to be allowed and treated differently from ["a", "b", "c"] in the first place. which is not the case if you initially were happy with list as a type hint.
This looks wrong, but I’m not sure I’m understanding what you’re saying. I’m not sure who your usages of “you” refer to, taking into account that the person designing the API, and the person implementing the function, and the person calling the function can all be different people. Who is “you”?
I agree with you that not using None is an improvement if you have a better option.
However, list | tuple with a default value isn’t an improvement? First, mutable defaults will make linters rightly complain even if you never seem to mutate the argument (it can be hard to verify that; what if you store it as a member variable?)
Second, tighter type annotations are usually better than loose ones, so either pick list or tuple, or if you truly support both because your function canonicalizes it, then choose Sequence.
Right, I think that’s for good reasons, but I guess we disagree
I guess you mean deferred evaluation? If so, then yes, this is probably the biggest motivator for it.