PEP 484 proposal: don't default to Optional if argument default is None

There's a proposal to change one detail of PEP 484. It currently says: An optional type is also automatically assumed when the default value is None, for example:: def handle_employee(e: Employee = None): ... This is equivalent to:: def handle_employee(e: Optional[Employee] = None) -> None: ... Now that we've got some experience actually using Optional with mypy (originally mypy ignored Optional), we're beginning to think that this was a bad idea. There's more discussion at https://github.com/python/typing/issues/275 and an implementation of the change (using a command-line flag) in https://github.com/python/mypy/pull/3248. Thoughts? Some function declarations will become a bit more verbose, but we gain clarity (many users of annotations don't seem to be familiar with this feature) and consistency (since this rule doesn't apply to variable declarations and class attribute declarations). -- --Guido van Rossum (python.org/~guido <http://python.org/%7Eguido>)

On 05/09/2017 10:28 AM, Guido van Rossum wrote:
There's a proposal to change one detail of PEP 484. It currently says:
An optional type is also automatically assumed when the default value is |None|, for example::
|def handle_employee(e: Employee = None): ... |
This is equivalent to::
|def handle_employee(e: Optional[Employee] = None) -> None: ... |
Now that we've got some experience actually using Optional with mypy (originally mypy ignored Optional), we're beginning to think that this was a bad idea. There's more discussion at https://github.com/python/typing/issues/275 and an implementation of the change (using a command-line flag) in https://github.com/python/mypy/pull/3248.
Thoughts? Some function declarations will become a bit more verbose, but we gain clarity (many users of annotations don't seem to be familiar with this feature) and consistency (since this rule doesn't apply to variable declarations and class attribute declarations).
I've been code-reviewing a lot of diffs adding type coverage over the last few months, and implicit-Optional has been among the most common points of confusion. So I favor this change. It might be nice to have a less verbose syntax for Optional, but that can be a separate discussion. Carl

On Tue, 9 May 2017 at 11:11 Carl Meyer <carl@oddbird.net> wrote:
On 05/09/2017 10:28 AM, Guido van Rossum wrote:
There's a proposal to change one detail of PEP 484. It currently says:
An optional type is also automatically assumed when the default value is |None|, for example::
|def handle_employee(e: Employee = None): ... |
This is equivalent to::
|def handle_employee(e: Optional[Employee] = None) -> None: ... |
Now that we've got some experience actually using Optional with mypy (originally mypy ignored Optional), we're beginning to think that this was a bad idea. There's more discussion at https://github.com/python/typing/issues/275 and an implementation of the change (using a command-line flag) in https://github.com/python/mypy/pull/3248.
Thoughts? Some function declarations will become a bit more verbose, but we gain clarity (many users of annotations don't seem to be familiar with this feature) and consistency (since this rule doesn't apply to variable declarations and class attribute declarations).
I've been code-reviewing a lot of diffs adding type coverage over the last few months, and implicit-Optional has been among the most common points of confusion. So I favor this change.
I personally like the shorthand, but the type hints I have written are in my own projects so my experience with others is zilch and shouldn't count for much.
It might be nice to have a less verbose syntax for Optional, but that can be a separate discussion.
You should be able to do that today with `from typing import Optional as Eh` or whatever your preferred optional/maybe name is. :)

On 10 May 2017 at 08:51, Brett Cannon <brett@python.org> wrote:
On Tue, 9 May 2017 at 11:11 Carl Meyer <carl@oddbird.net> wrote:
It might be nice to have a less verbose syntax for Optional, but that can be a separate discussion.
You should be able to do that today with `from typing import Optional as Eh` or whatever your preferred optional/maybe name is. :)
While "from typing import Optional as Opt" can indeed help, perhaps PEP 505 should be updated to discuss this point in addition to the current proposals for None-aware binary operators? If it included a ? prefix operator as a shorthand for "typing.Optional[<expr>]", that would shorten affected declarations back to: def handle_employee(e: ?Employee = None) -> None: ... Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Tue, May 9, 2017 at 7:37 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
On 10 May 2017 at 08:51, Brett Cannon <brett@python.org> wrote:
On Tue, 9 May 2017 at 11:11 Carl Meyer <carl@oddbird.net> wrote:
It might be nice to have a less verbose syntax for Optional, but that can be a separate discussion.
You should be able to do that today with `from typing import Optional as Eh` or whatever your preferred optional/maybe name is. :)
While "from typing import Optional as Opt" can indeed help, perhaps PEP 505 should be updated to discuss this point in addition to the current proposals for None-aware binary operators?
If it included a ? prefix operator as a shorthand for "typing.Optional[<expr>]", that would shorten affected declarations back to:
def handle_employee(e: ?Employee = None) -> None: ...
I really don't want to go there. And this idea should definitely not be a condition for removing the existing PEP 484 feature. Whatever gets done syntax-wise won't affect anyone who needs any kind of backward compatibility anyways, and that's very important for practical adoption of PEP 484. -- --Guido van Rossum (python.org/~guido)

There is a discrepancy now between PEP 484 and PEP 526: def f(x: int = None): ... # OK x: int = None # Error I think the two rules should be "in sync", in view of this I agree with the proposal. Concerning verbosity and a long name Optional there are many reasonable workarounds. One is already mentioned from typing import Optional as O. Another (unrelated to `` = None`` pattern) is https://github.com/python/typing/issues/420 that allows to avoid Optional altogether in patterns like this: def func(x: Optional[X]) -> Optional[Y]: if x is None: return None # do some stuff with 'x' With @maybe decorator proposed in https://github.com/python/typing/issues/420 this will be simplified to: @maybe def func(x: X) -> Y: if x is None: return None # do some stuff with 'x' Even if @maybe will not make it to typing, one still can define such (or similar) decorators (especially with @decorated_type and extended Callable syntax). In view of this, I think verbosity is not a problem at all. -- Ivan
participants (5)
-
Brett Cannon
-
Carl Meyer
-
Guido van Rossum
-
Ivan Levkivskyi
-
Nick Coghlan