In my codebase there is some amount of None.__class__
.
PyCharm marks this as as a warning:
Cannot find reference '__class__' in 'None'
I am using PyCharm 2022.3 (Community Edition) if that matters.
However, when I try it out in REPL I get this sensible output which seems to be consistent across different python versions (including Python 2.7 and Python 3.10) from what I have tried:
>>> None.__class__
<type 'NoneType'>
Is there a hidden danger I am not seeing?
The documentation https://docs.python.org/3/library/constants.html#None seems to suggest NoneType
is a proper part of the language and not some implementation-quirk.
Location of the
NoneType
has changed across Python versions, see Where is the NoneType located?The two main ways of getting
NoneType
from Python 3.10 onward are calling the builtintype(None)
or importing it, both are equivalent although usingtype(None)
saves one import:You may need to adjust PyCharm's inspections to be version specific for your project, see Wrong Python version in PyCharm's inspections.
Using builtin functions, in this case type(), is always preferred. Calling the builtin
type()
would also be portable across Python versions.The alternative of calling the
__class__
descriptor directly makes things generally more complicated, see Difference between type(obj) and obj.__class__ and also Python __class__(). Lastly, in typeshed theNoneType
is remarkably simple.I do not think that this is a PyCharm linter bug but that the warning follows the same trend as mypy, see Warn when NoneType is used in a type #11288 and Treating NoneType as None and warning against using NoneType. #13153.
In effect, using mypy on the snippet:
gives:
If instead we use
builtins.type
with subscripting (see the end note under the deprecatedtyping.Type
):Mypy doesn't complain (and neither does the PyCharm linter):