Any possible type alias that can also set a default value for a function arg?

Chris Angelico rosuav at gmail.com
Wed Oct 18 19:30:30 EDT 2023


On Thu, 19 Oct 2023 at 10:11, Matthew Carruth via Python-list
<python-list at python.org> wrote:
>
> We have the `Optional[T]` type as a short-hand for Union[T | None] and telling us that said argument may not be present.
>
> However, I find that a majority of the time, we also want to set a default value of None on the argument so that it can be evaluated without doing a getattr() check first.
>
> iow, a lot of `foo: Optional[str] = None` in method signatures.
>
> I'd love to see a companion to the Optional type, I'll call it Default, so that it can take a default value as a second arg, with a default of that being None.
>
> For example:
>
> foo: Default[str] would be equivalent to foo: Optional[str] = None
> foo: Default[str, "bar"] would be equivalent to foo: Optional[str] = "bar"
>
> or something like that. Basically, any way to avoid writing `= None` over and over again.

Fundamentally no, at least not without some shenanigans. Type hints do
not affect the regular running of the code, so they can't add
defaults. You could do it the other way around and have the default
imply that it is optional, and I believe that used to be the way that
MyPy calculated things, but it was ultimately rejected. (I may have
the details wrong on that though, don't quote me.)

Ahh, but shenanigans? What kind of shenanigans is that? Glad you
asked! So, uhh, you could decorate a function and mess with its
defaults.

>>> from typing import Optional
>>> def spam(n: Optional[int]):
...     if n is None: print("Default spamminess")
...     else: print("Spam " * n)
...
>>> spam(5)
Spam Spam Spam Spam Spam
>>> spam(None)
Default spamminess
>>> spam()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: spam() missing 1 required positional argument: 'n'
>>> spam.__defaults__ = (None,)
>>> spam()
Default spamminess

So you could design a decorator that goes through all the arguments,
finds the ones that say "Optional", and adds a default of None if one
wasn't specified. Good luck with it though. First, you'll have to deal
with the difficulties of aligning arguments (not insurmountable but a
lot of work; don't forget that there are posonly and kwonly args to
consider). Then, you'll have to deal with the much bigger difficulties
of convincing people that this is a good thing.

BTW, rather than a decorator, you could do this by iterating over
every function in a module or class. That might work out easier. Not
sure.

Just be aware that, while Python provides you with all the tools
necessary to shoot yourself in the foot, that isn't a guarantee that
holes in feet are worthwhile.

ChrisA


More information about the Python-list mailing list