For reasons out of scope of this question, I'm building a serialization mechanism. I've run into a problem with None
objects that I think I need to special case. Can anybody explain why NoneType
is treated differently from other builtin types? Or am I missing something?
>>> import sys
>>> builtin = sys.modules['__builtin__']
>>> getattr(builtin,'int')
<type 'int'>
>>> getattr(builtin,'list')
<type 'list'>
>>> getattr(builtin,'NoneType')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'NoneType'
python 2.6.5 on Ubuntu
Of course
getattr(builtin,'None')
works and returns a None
object, which is an instance of NoneType
. But the class object exists in the __builtin__
module for everything else. So this code works for every built in type except None
:
klass = getattr(builtin, obj.__class__.__name__)
which makes sense given that
>>> type(0).__module__
'__builtin__'
>>> type("foo").__module__
'__builtin__'
>>> type(None).__module__
'__builtin__'
The fact that this fails for None
seems like an oversight in Python, unless I'm missing something.
I suppose what you call NoneType
is treated specially because you hardly never need to access it. You could say
>>> NoneType = type(None)
to bind this type to a name, but that would serve no common purpose: isinstance(x, NoneType)
would be a contrived equivalent to x is None
; the constructor raises a TypeError
stating that you're not supposed to construct instances; and deriving from it is forbidden too.
You can still get to the type via either type(None)
, None.__class__
, or types.NoneType
, though, if you need it for some advanced purpose.
NoneType is available in the types module.
>>> import types
>>> types.NoneType
<type 'NoneType'>
Infact types module is the right place to use if you are doing anything with types, don't rely on types being present in the builtins
It is probably to do something with the fact that None is not really a type, it sa builtin constant . Even the docs say the type of None is types.NoneType, but you are right it is implemented in a special manner and is inconsistent from all other types.
It is odd. But so are plenty of odd things about classes and objects in python 2. This is true of a bunch of languages that evolved from simple scripts to full-fledged OO. Python 3 is intended to solve this.
NoneType is a special case already because it is the class object for a singleton, so it can't be called as a constructor.
TypeError: cannot create 'NoneType' instances
So, if you are writing a general serializer then you will need to special case None anyway, irregardless of whether you can't look up the class object.
Have you tried looking at:
>>> dir(builtin)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
NoneType
is not listed as a builtin type (even though None
is)
you should try : getattr(builtin,"None")
not getattr(builtin,"NoneType")
, as NoneType
is the value of type(None)
, so it's not an attribute of builtin
.
In [49]: type(None)
Out[49]: <type 'NoneType'>
this doesn't works, as Python is not able to find out NoneType
anywhere.
In [50]: type(NoneType)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/home/monty/<ipython console> in <module>()
NameError: name 'NoneType' is not defined
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.