I found out from docs:
Note that
Noneas a type hint is a special case and is replaced bytype(None).
However, I don't find this to be the case in practice (Using Python 3.8.5, iPython 7.16.1). For example:
- If I use
type(None)to annotate a variable:
In [1]: class Foo:
...: a: int
...: b: str
...: c: type(None)
In [2]: Foo.__annotations__
Out[2]: {'a': int, 'b': str, 'c': NoneType}
In [3]: for k, v in Foo.__annotations.__.items():
...: print(f'Default for {k} -> {v()!r} {v}')
Default for a -> 0 <class 'int'>
Default for b -> '' <class 'str'>
Default for c -> None <class 'NoneType'>
- Whereas, using simply
Noneproduces error:
In [4]: class Foo:
...: a: int
...: b: str
...: c: None
In [5]: Foo.__annotations__
Out[5]: {'a': int, 'b': str, 'c': None}
In [6]: for k, v in Foo.__annotations.__.items():
...: print(f'Default for {k} -> {v()!r} {v}')
Default for a -> 0 <class 'int'>
Default for b -> '' <class 'str'>
Traceback (most recent call last):
File "<ipython-input-40-d9b0ce31b437>", line 2, in <module>
print(f'Default for {k} -> {v()!r} {v}')
TypeError: 'NoneType' object is not callable
So what is happening? What does the line from the doc mean? Is it specifically for the linters and does not affect the actual annotations? If so why not enforce type(None) while hinting, or convert None to type(None) in the annotations dict as well, instead of having two different behaviors in almost similar contexts? I guess this is the reason they are bringing back types.NoneType in 3.10?