What is a None value?
Solution 1:
Martijn's answer explains what None
is in Python, and correctly states that the book is misleading. Since Python programmers as a rule would never say
Assigning a value of
None
to a variable is one way to reset it to its original, empty state.
it's hard to explain what Briggs means in a way which makes sense and explains why no one here seems happy with it. One analogy which may help:
In Python, variable names are like stickers put on objects. Every sticker has a unique name written on it, and it can only be on one object at a time, but you could put more than one sticker on the same object, if you wanted to. When you write
F = "fork"
you put the sticker "F" on a string object "fork"
. If you then write
F = None
you move the sticker to the None
object.
What Briggs is asking you to imagine is that you didn't write the sticker "F"
, there was already an F
sticker on the None
, and all you did was move it, from None
to "fork"
. So when you type F = None
, you're "reset[ting] it to its original, empty state", if we decided to treat None
as meaning empty state
.
I can see what he's getting at, but that's a bad way to look at it. If you start Python and type print(F)
, you see
>>> print(F)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'F' is not defined
and that NameError
means Python doesn't recognize the name F
, because there is no such sticker. If Briggs were right and F = None
resets F
to its original state, then it should be there now, and we should see
>>> print(F)
None
like we do after we type F = None
and put the sticker on None
.
So that's all that's going on. In reality, Python comes with some stickers already attached to objects (built-in names), but others you have to write yourself with lines like F = "fork"
and A = 2
and c17 = 3.14
, and then you can stick them on other objects later (like F = 10
or F = None
; it's all the same.)
Briggs is pretending that all possible stickers you might want to write were already stuck to the None
object.
Solution 2:
None
is just a value that commonly is used to signify 'empty', or 'no value here'. It is a signal object; it only has meaning because the Python documentation says it has that meaning.
There is only one copy of that object in a given Python interpreter session.
If you write a function, and that function doesn't use an explicit return
statement, None
is returned instead, for example. That way, programming with functions is much simplified; a function always returns something, even if it is only that one None
object.
You can test for it explicitly:
if foo is None:
# foo is set to None
if bar is not None:
# bar is set to something *other* than None
Another use is to give optional parameters to functions an 'empty' default:
def spam(foo=None):
if foo is not None:
# foo was specified, do something clever!
The function spam()
has a optional argument; if you call spam()
without specifying it, the default value None
is given to it, making it easy to detect if the function was called with an argument or not.
Other languages have similar concepts. SQL has NULL
; JavaScript has undefined
and null
, etc.
Note that in Python, variables exist by virtue of being used. You don't need to declare a variable first, so there are no really empty variables in Python. Setting a variable to None
is then not the same thing as setting it to a default empty value; None
is a value too, albeit one that is often used to signal emptyness. The book you are reading is misleading on that point.
Solution 3:
This is what the Python documentation has got to say about None
:
The sole value of types.NoneType. None is frequently used to represent the absence of a value, as when default arguments are not passed to a function.
Changed in version 2.4: Assignments to None are illegal and raise a SyntaxError.
Note The names None and debug cannot be reassigned (assignments to them, even as an attribute name, raise SyntaxError), so they can be considered “true” constants.
-
Let's confirm the type of
None
firstprint type(None) print None.__class__
Output
<type 'NoneType'> <type 'NoneType'>
Basically, NoneType
is a data type just like int
, float
, etc. You can check out the list of default types available in Python in 8.15. types — Names for built-in types.
-
And,
None
is an instance ofNoneType
class. So we might want to create instances ofNone
ourselves. Let's try thatprint types.IntType() print types.NoneType()
Output
0 TypeError: cannot create 'NoneType' instances
So clearly, cannot create NoneType
instances. We don't have to worry about the uniqueness of the value None
.
-
Let's check how we have implemented
None
internally.print dir(None)
Output
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
Except __setattr__
, all others are read-only attributes. So, there is no way we can alter the attributes of None
.
-
Let's try and add new attributes to
None
setattr(types.NoneType, 'somefield', 'somevalue') setattr(None, 'somefield', 'somevalue') None.somefield = 'somevalue'
Output
TypeError: can't set attributes of built-in/extension type 'NoneType' AttributeError: 'NoneType' object has no attribute 'somefield' AttributeError: 'NoneType' object has no attribute 'somefield'
The above seen statements produce these error messages, respectively. It means that, we cannot create attributes dynamically on a None
instance.
-
Let us check what happens when we assign something
None
. As per the documentation, it should throw aSyntaxError
. It means, if we assign something toNone
, the program will not be executed at all.None = 1
Output
SyntaxError: cannot assign to None
We have established that
-
None
is an instance ofNoneType
-
None
cannot have new attributes - Existing attributes of
None
cannot be changed. - We cannot create other instances of
NoneType
- We cannot even change the reference to
None
by assigning values to it.
So, as mentioned in the documentation, None
can really be considered as a true constant
.
Happy knowing None
:)
Solution 4:
The book you refer to is clearly trying to greatly simplify the meaning of None
. Python variables don't have an initial, empty state – Python variables are bound (only) when they're defined. You can't create a Python variable without giving it a value.
>>> print(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> def test(x):
... print(x)
...
>>> test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: test() takes exactly 1 argument (0 given)
>>> def test():
... print(x)
...
>>> test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in test
NameError: global name 'x' is not defined
but sometimes you want to make a function mean different things depending on whether a variable is defined or not. You can create an argument with a default value of None
:
>>> def test(x=None):
... if x is None:
... print('no x here')
... else:
... print(x)
...
>>> test()
no x here
>>> test('x!')
x!
The fact that this value is the special None
value is not terribly important in this case. I could've used any default value:
>>> def test(x=-1):
... if x == -1:
... print('no x here')
... else:
... print(x)
...
>>> test()
no x here
>>> test('x!')
x!
…but having None
around gives us two benefits:
- We don't have to pick a special value like
-1
whose meaning is unclear, and - Our function may actually need to handle
-1
as a normal input.
>>> test(-1)
no x here
oops!
So the book is a little misleading mostly in its use of the word reset – assigning None
to a name is a signal to a programmer that that value isn't being used or that the function should behave in some default way, but to reset a value to its original, undefined state you must use the del
keyword:
>>> x = 3
>>> x
3
>>> del x
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
Solution 5:
Other answers have already explained meaning of None beautifully. However, I would still like to throw more light on this using an example.
Example:
def extendList(val, list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3
Now try to guess output of above list. Well, the answer is surprisingly as below:
list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']
But Why?
Many will mistakenly expect list1 to be equal to [10] and list3 to be equal to ['a'], thinking that the list argument will be set to its default value of [] each time extendList is called.
However, what actually happens is that the new default list is created only once when the function is defined, and that same list is then used subsequently whenever extendList is invoked without a list argument being specified. This is because expressions in default arguments are calculated when the function is defined, not when it’s called.
list1 and list3 are therefore operating on the same default list, whereas list2 is operating on a separate list that it created (by passing its own empty list as the value for the list parameter).
'None' the savior: (Modify example above to produce desired behavior)
def extendList(val, list=None):
if list is None:
list = []
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3
With this revised implementation, the output would be:
list1 = [10]
list2 = [123]
list3 = ['a']
Note - Example credit to toptal.com