Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

[Python-ideas] Confusing naming of Optional type should be changed

20 views
Skip to first unread message

nver...@gmail.com

unread,
Jun 30, 2022, 1:48:12 PM6/30/22
to python...@python.org
(I apologize in advance if I've posted anything incorrectly before, I believe I might have sent this in python-dev instead but not sure as it's not appearing in the posts for my account).

I am aware this is clarified in the Python documentation for the typing module but I and others have thought the naming of Optional is still quite confusing by itself.

"Note that this is not the same concept as an optional argument, which is one that has a default. An optional argument with a default does not require the Optional qualifier on its type annotation just because it is optional." - typing.Optional docs

Google defines optional as this, "available to be chosen but not obligatory."

Pretend we have a function like this:
def test_func(param: Optional[str]) -> None:
...

The argument param is typed as Optional[str] meaning Union[str, None] or str | None. Optional here if we follow the definition above, basically means it can be str but not required or obligated to be that type. See the problem with the naming? This is a function where param can be None or str, not just it can be str but not obligated. Some interpretations may think optional means left to one's choice as well. The docs even have to clarify the use of Optional with typing because of this confusion.

I believe this has been proposed before (not sure) but something like Nullable or Noneable (not sure about naming) would make much more sense in the context of typing.
def test_func(param: Noneable[str]) -> None:
...

It also would work and still make sense if there is a default value for the argument:
def test_func(param: Noneable[str] = None) -> None:
...

def test_func(param: Noneable[str] = "hello world") -> None:
...
_______________________________________________
Python-ideas mailing list -- python...@python.org
To unsubscribe send an email to python-id...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python...@python.org/message/GV3ZHUYFAO2GM7PP4UX4JEMBEBOHRNQW/
Code of Conduct: http://python.org/psf/codeofconduct/

Jelle Zijlstra

unread,
Jun 30, 2022, 1:50:55 PM6/30/22
to nver...@gmail.com, python-ideas
El jue, 30 jun 2022 a las 10:46, <nver...@gmail.com> escribió:
(I apologize in advance if I've posted anything incorrectly before, I believe I might have sent this in python-dev instead but not sure as it's not appearing in the posts for my account).

I am aware this is clarified in the Python documentation for the typing module but I and others have thought the naming of Optional is still quite confusing by itself.

"Note that this is not the same concept as an optional argument, which is one that has a default. An optional argument with a default does not require the Optional qualifier on its type annotation just because it is optional." - typing.Optional docs

Google defines optional as this, "available to be chosen but not obligatory."

Pretend we have a function like this:
def test_func(param: Optional[str]) -> None:
    ...

The argument param is typed as Optional[str] meaning Union[str, None] or str | None. Optional here if we follow the definition above, basically means it can be str but not required or obligated to be that type. See the problem with the naming? This is a function where param can be None or str, not just it can be str but not obligated. Some interpretations may think optional means left to one's choice as well. The docs even have to clarify the use of Optional with typing because of this confusion.

I believe this has been proposed before (not sure) but something like Nullable or Noneable (not sure about naming) would make much more sense in the context of typing.
def test_func(param: Noneable[str]) -> None:
    ...

It also would work and still make sense if there is a default value for the argument:
def test_func(param: Noneable[str] = None) -> None:
    ...

def test_func(param: Noneable[str] = "hello world") -> None:
    ...


This problem has already been solved: in Python 3.10, thanks to PEP 604, you can write `str | None` instead of `Optional[str]`.

nver...@gmail.com

unread,
Jun 30, 2022, 2:16:37 PM6/30/22
to python...@python.org
I accidentally created another thread in python-dev as I mentioned above, but ideally Optional and Union should both be deprecated and phased out for the new syntax.
_______________________________________________
Python-ideas mailing list -- python...@python.org
To unsubscribe send an email to python-id...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python...@python.org/message/ZYRRN4KUZUKUFPTYIBL6K6LCTOU6MIDX/

Stephen J. Turnbull

unread,
Jul 1, 2022, 1:19:12 AM7/1/22
to nver...@gmail.com, python...@python.org
nver...@gmail.com writes:

> I accidentally created another thread in python-dev as I mentioned
> above, but ideally Optional and Union should both be deprecated and
> phased out for the new syntax.

I think a formal deprecation is a bad idea. An annotation is an
object, which has a type. Both the object and the type are going to
be visible to users. We don't want there to be warnings about them
forever, and Python as a rule does not formally deprecate working code
that is expected to continue to work indefinitely.

I suspect that it would be difficult to get a stylistic deprecation
into PEP 8 (IIRC type annotations are still not allowed in stdlib code
so it would be considered out of scope), but you could try lobbying
the maintainers of linters.

BTW, I disagree with your arguments that Optional and Union are
misleading names that can be easily misunderstood, especially in the
usual context of formal arguments in function definitions. The
suggestion of "Noneable" takes the Pythonic implementation of optional
arguments (by defaulting to None) too seriously, at the expense of the
syntactic intention: an argument that may be omitted. Among other
things, very frequently 'None' is *not* an allowed value in the body
of the function, some other value is immediately substituted (and PEP
671 explicitly tries to automate this process for the common case of a
mutable default that should be constructed at call time, so that even
the idiomatic "if arg is None" statement is left out).

"Optional" is the normal term used for such arguments, "union" is the
technical term for types composed of being either this or that type.
If you need to know any more than that about those types, you're going
to have to study up no matter what terms are used. That's just the
nature of using natural language words to name things that have a
precise definition and implementation in software. Study is required.

Steve
_______________________________________________
Python-ideas mailing list -- python...@python.org
To unsubscribe send an email to python-id...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python...@python.org/message/LELXP5FPJZWF36NR423ZLVOHGXQTUVKL/

Thomas Grainger

unread,
Jul 1, 2022, 5:30:41 AM7/1/22
to Stephen J. Turnbull, nver...@gmail.com, python-ideas
The generic collections in typing were deprecated in favor of the generic collections in collections.abc. The objects and the types were exposed to user code, and in the future they will not be

> We don't want there to be warnings about them
> forever

The new  wanrings._deprecated https://discuss.python.org/t/introducing-warnings-deprecated/14856 automatically removes features, so deprecations cannot be forgotten anymore 

Jelle Zijlstra

unread,
Jul 1, 2022, 10:18:06 AM7/1/22
to Stephen J. Turnbull, nver...@gmail.com, python-ideas
In fact, `typing.Optional` means that something can be None, *not* that it is an optional argument.

In other words:

def f(x: Optional[str], y: int = 0): ...

f(x=None)  # allowed
f()  # not allowed (x is omitted)
f(x="", y=None)  # not allowed (y cannot be None)

That's the opposite of what you describe, so really you're making an argument against the use of the Optional term.

nver...@gmail.com

unread,
Jul 1, 2022, 10:50:01 AM7/1/22
to python...@python.org
> BTW, I disagree with your arguments that Optional and Union are
> misleading names that can be easily misunderstood, especially in the
> usual context of formal arguments in function definitions.

The comment made by Jelle Zijlstra suggested to me suggested that the new syntax might have been a replacer for Union as well, as that is really what the `|` is. I want to clarify though that I do not think Union is a confusing name as Optional. My main argument in the first place was that Optional was a potentially perplexing name choice.

> The suggestion of "Noneable" takes the Pythonic implementation of optional
> arguments (by defaulting to None) too seriously, at the expense of the
> syntactic intention: an argument that may be omitted. Among other
> things, very frequently 'None' is *not* an allowed value in the body
> of the function

It is kind of an edge case scenario from most common applications in Python. Still, if someone were to allow both None and some other type, I would think using Optional for the naming is more incoherent when it really isn't "optional" if you look at the type alone based on the definition.
_______________________________________________
Python-ideas mailing list -- python...@python.org
To unsubscribe send an email to python-id...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python...@python.org/message/HCD4PODP5XEZ3P4ZKQIEZGJL3EANRQRR/

Stephen J. Turnbull

unread,
Jul 2, 2022, 5:20:44 AM7/2/22
to Jelle Zijlstra, nver...@gmail.com, python-ideas
Jelle Zijlstra writes:

> In fact, `typing.Optional` means that something can be None, *not*
> that it is an optional argument.

You're missing my point. Yes, the *implementation* is that the object
can be None. But that's far more clearly expressed by Union[T, None]
if that's what you *mean*, and it only costs 3 characters. Optional
clearly was intended to mean that this type is for use in optional
arguments.

Having "Optional" at all may have been a bad choice, since (1) it is
redundant given you still need to specify "= None" to actually make it
optional, and (2) usually shouldn't be used for optional arguments
that don't default to None (because in such cases None usually isn't
an acceptable argument). I am persuaded of that now: it doesn't
express the idea "this type is for use in optional formal arguments".

But I am convinced by arguments about the *language* (including type
expressions) that are about *what it expresses*, as in the paragraph
above (natural language) or your example function f (code example).
Arguments about what something *is* in the implementation, or vague
statements that things "could" be misinterpreted aren't terribly
helpful to me, YMMV. And I think they lead to bad decisions about the
language.
_______________________________________________
Python-ideas mailing list -- python...@python.org
To unsubscribe send an email to python-id...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python...@python.org/message/LLHRUM3CNBLVAX7VCFTZ6ZUPBVEXNBS7/

Kevin Mills

unread,
Jul 12, 2022, 1:54:30 PM7/12/22
to python...@python.org
While confusion with optional arguments is somewhat unfortunate, the name came from an already established convention. A lot of languages have exactly the same concept, varying between names like Optional, Option, and Maybe. I don't think coming up with a Python-specific name for the same thing is necessarily better.

Of course, it's immaterial now that the union syntax is preferred.
_______________________________________________
Python-ideas mailing list -- python...@python.org
To unsubscribe send an email to python-id...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python...@python.org/message/4IAHIQ4V6UOGH2AJX46KWTXVBUJEP3MJ/

Stephen J. Turnbull

unread,
Jul 13, 2022, 12:34:53 AM7/13/22
to Kevin Mills, python...@python.org
Kevin Mills writes:

> While confusion with optional arguments is somewhat unfortunate,
> the name came from an already established convention. A lot of
> languages have exactly the same concept, varying between names like
> Optional, Option, and Maybe. I don't think coming up with a
> Python-specific name for the same thing is necessarily better.

This seems likely to be more or less moot. If you're interested, see
Guido's (!!) new PEP 695 (pretty sure that's the number, need to go to
meeting that is starting, sorry).

>
> Of course, it's immaterial now that the union syntax is preferred.
> _______________________________________________
> Python-ideas mailing list -- python...@python.org
> To unsubscribe send an email to python-id...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at https://mail.python.org/archives/list/python...@python.org/message/4IAHIQ4V6UOGH2AJX46KWTXVBUJEP3MJ/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>
_______________________________________________
Python-ideas mailing list -- python...@python.org
To unsubscribe send an email to python-id...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python...@python.org/message/FDTTV5Q7LSN3MAJGAUWPQ64Z4HULS7LX/
Reply all
Reply to author
Forward
0 new messages