Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python's None: Null in Python
If you have experience with other programming languages, like C or Java, then you’ve probably heard of the concept of null
. Many languages use this to represent a pointer that doesn’t point to anything, to denote when a variable is empty, or to mark default parameters that you haven’t yet supplied. null
is often defined to be 0
in those languages, but null
in Python is different.
Python uses the keyword None
to define null
objects and variables. While None
does serve some of the same purposes as null
in other languages, it’s another beast entirely. As the null
in Python, None
is not defined to be 0
or any other value. In Python, None
is an object and a first-class citizen!
In this tutorial, you’ll learn:
- What
None
is and how to test for it - When and why to use
None
as a default parameter - What
None
andNoneType
mean in your traceback - How to use
None
in type checking - How
null
in Python works under the hood
Free Bonus: Click here to get a Python Cheat Sheet and learn the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.
Understanding Null in Python
None
is the value a function returns when there is no return
statement in the function:
>>> def has_no_return():
... pass
>>> has_no_return()
>>> print(has_no_return())
None
When you call has_no_return()
, there’s no output for you to see. When you print a call to it, however, you’ll see the hidden None
it returns.
In fact, None
so frequently appears as a return value that the Python REPL won’t print None
unless you explicitly tell it to:
>>> None
>>> print(None)
None
None
by itself has no output, but printing it displays None
to the console.
Interestingly, print()
itself has no return value. If you try to print a call to print()
, then you’ll get None
:
>>> print(print("Hello, World!"))
Hello, World!
None
It may look strange, but print(print("..."))
shows you the None
that the inner print()
returns.
None
also often used as a signal for missing or default parameters. For instance, None
appears twice in the docs for list.sort
:
>>> help(list.sort)
Help on method_descriptor:
sort(...)
L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*
Here, None
is the default value for the key
parameter as well as the type hint for the return value. The exact output of help
can vary from platform to platform. You may get different output when you run this command in your interpreter, but it will be similar.
Using Python’s Null Object None
Often, you’ll use None
as part of a comparison. One example is when you need to check and see if some result or parameter is None
. Take the result you get from re.match
. Did your regular expression match a given string? You’ll see one of two results:
- Return a
Match
object: Your regular expression found a match. - Return a
None
object: Your regular expression did not find a match.
In the code block below, you’re testing if the pattern "Goodbye"
matches a string:
>>> import re
>>> match = re.match(r"Goodbye", "Hello, World!")
>>> if match is None:
... print("It doesn't match.")
It doesn't match.
Here, you use is None
to test if the pattern matches the string "Hello, World!"
. This code block demonstrates an important rule to keep in mind when you’re checking for None
:
- Do use the identity operators
is
andis not
. - Do not use the equality operators
==
and!=
.
The equality operators can be fooled when you’re comparing user-defined objects that override them:
>>> class BrokenComparison:
... def __eq__(self, other):
... return True
>>> b = BrokenComparison()
>>> b == None # Equality operator
True
>>> b is None # Identity operator
False
Here, the equality operator ==
returns the wrong answer. The identity operator is
, on the other hand, can’t be fooled because you can’t override it.
Note: For more info on how to compare with None
, check out Do’s and Dont’s: Python Programming Recommendations.
None
is falsy, which means not None
is True
. If all you want to know is whether a result is falsy, then a test like the following is sufficient:
>>> some_result = None
>>> if some_result:
... print("Got a result!")
... else:
... print("No result.")
...
No result.
The output doesn’t show you that some_result
is exactly None
, only that it’s falsy. If you must know whether or not you have a None
object, then use is
and is not
.
The following objects are all falsy as well:
- Empty lists
- Empty dictionaries
- Empty sets
- Empty strings
0
False
For more on comparisons, truthy values, and falsy values, you can read about how to use the Python or
operator, how to use the Python and
operator, and how to use the Python not
operator.
Declaring Null Variables in Python
In some languages, variables come to life from a declaration. They don’t have to have an initial value assigned to them. In those languages, the initial default value for some types of variables might be null
. In Python, however, variables come to life from assignment statements. Take a look at the following code block:
>>> print(bar)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'bar' is not defined
>>> bar = None
>>> print(bar)
None
Here, you can see that a variable with the value None
is different from an undefined variable. All variables in Python come into existence by assignment. A variable will only start life as null
in Python if you assign None
to it.
Using None
as a Default Parameter
Very often, you’ll use None
as the default value for an optional parameter. There’s a very good reason for using None
here rather than a mutable type such as a list. Imagine a function like this:
def bad_function(new_elem, starter_list=[]):
starter_list.append(new_elem)
return starter_list
bad_function()
contains a nasty surprise. It works fine when you call it with an existing list:
>>> my_list = ['a', 'b', 'c']
>>> bad_function('d', my_list)
['a', 'b', 'c', 'd']
Here, you add 'd'
to the end of the list with no problems.
But if you call this function a couple times with no starter_list
parameter, then you start to see incorrect behavior:
>>> bad_function('a')
['a']
>>> bad_function('b')
['a', 'b']
>>> bad_function('c')
['a', 'b', 'c']
The default value for starter_list
evaluates only once at the time the function is defined, so the code reuses it every time you don’t pass an existing list.
The right way to build this function is to use None
as the default value, then test for it and instantiate a new list as needed:
1>>> def good_function(new_elem, starter_list=None):
2... if starter_list is None:
3... starter_list = []
4... starter_list.append(new_elem)
5... return starter_list
6...
7>>> good_function('e', my_list)
8['a', 'b', 'c', 'd', 'e']
9>>> good_function('a')
10['a']
11>>> good_function('b')
12['b']
13>>> good_function('c')
14['c']
good_function()
behaves as you want by making a new list with each call where you don’t pass an existing list. It works because your code will execute lines 2 and 3 every time it calls the function with the default parameter.
Using None
as a Null Value in Python
What do you do when None
is a valid input object? For instance, what if good_function()
could either add an element to the list or not, and None
was a valid element to add? In this case, you can define a class specifically for use as a default, while being distinct from None
:
>>> class DontAppend: pass
...
>>> def good_function(new_elem=DontAppend, starter_list=None):
... if starter_list is None:
... starter_list = []
... if new_elem is not DontAppend:
... starter_list.append(new_elem)
... return starter_list
...
>>> good_function(starter_list=my_list)
['a', 'b', 'c', 'd', 'e']
>>> good_function(None, my_list)
['a', 'b', 'c', 'd', 'e', None]
Here, the class DontAppend
serves as the signal not to append, so you don’t need None
for that. That frees you to add None
when you want.
You can use this technique when None
is a possibility for return values, too. For instance, dict.get
returns None
by default if a key is not found in the dictionary. If None
was a valid value in your dictionary, then you could call dict.get
like this:
>>> class KeyNotFound: pass
...
>>> my_dict = {'a':3, 'b':None}
>>> for key in ['a', 'b', 'c']:
... value = my_dict.get(key, KeyNotFound)
... if value is not KeyNotFound:
... print(f"{key}->{value}")
...
a->3
b->None
Here you’ve defined a custom class KeyNotFound
. Now, instead of returning None
when a key isn’t in the dictionary, you can return KeyNotFound
. That frees you to return None
when that’s the actual value in the dictionary.
Deciphering None
in Tracebacks
When NoneType
appears in your traceback, it means that something you didn’t expect to be None
actually was None
, and you tried to use it in a way that you can’t use None
. Almost always, it’s because you’re trying to call a method on it.
For instance, you called append()
on my_list
many times above, but if my_list
somehow became anything other than a list, then append()
would fail:
>>> my_list.append('f')
>>> my_list
['a', 'b', 'c', 'd', 'e', None, 'f']
>>> my_list = None
>>> my_list.append('g')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'append'
Here, your code raises the very common AttributeError
because the underlying object, my_list
, is not a list anymore. You’ve set it to None
, which doesn’t know how to append()
, and so the code throws an exception.
When you see a traceback like this in your code, look for the attribute that raised the error first. Here, it’s append()
. From there, you’ll see the object you tried to call it on. In this case, it’s my_list
, as you can tell from the code just above the traceback. Finally, figure out how that object got to be None
and take the necessary steps to fix your code.
Checking for Null in Python
There are two type checking cases where you’ll care about null
in Python. The first case is when you’re returning None
:
>>> def returns_None() -> None:
... pass
This case is similar to when you have no return
statement at all, which returns None
by default.
The second case is a bit more challenging. It’s where you’re taking or returning a value that might be None
, but also might be some other (single) type. This case is like what you did with re.match
above, which returned either a Match
object or None
.
The process is similar for parameters:
from typing import Any, List, Optional
def good_function(new_elem:Any, starter_list:Optional[List]=None) -> List:
pass
You modify good_function()
from above and import Optional
from typing
to return an Optional[Match]
.
Taking a Look Under the Hood
In many other languages, null
is just a synonym for 0
, but null
in Python is a full-blown object:
>>> type(None)
<class 'NoneType'>
This line shows that None
is an object, and its type is NoneType
.
None
itself is built into the language as the null
in Python:
>>> dir(__builtins__)
['ArithmeticError', ..., 'None', ..., 'zip']
Here, you can see None
in the list of __builtins__
which is the dictionary the interpreter keeps for the builtins
module.
None
is a keyword, just like True
and False
. But because of this, you can’t reach None
directly from __builtins__
as you could, for instance, ArithmeticError
. However, you can get it with a getattr()
trick:
>>> __builtins__.ArithmeticError
<class 'ArithmeticError'>
>>> __builtins__.None
File "<stdin>", line 1
__builtins__.None
^
SyntaxError: invalid syntax
>>> print(getattr(__builtins__, 'None'))
None
When you use getattr()
, you can fetch the actual None
from __builtins__
, which you can’t do by simply asking for it with __builtins__.None
.
Even though Python prints the word NoneType
in many error messages, NoneType
is not an identifier in Python. It’s not in builtins
. You can only reach it with type(None)
.
None
is a singleton. That is, the NoneType
class only ever gives you the same single instance of None
. There’s only one None
in your Python program:
>>> my_None = type(None)() # Create a new instance
>>> print(my_None)
None
>>> my_None is None
True
Even though you try to create a new instance, you still get the existing None
.
You can prove that None
and my_None
are the same object by using id()
:
>>> id(None)
4465912088
>>> id(my_None)
4465912088
Here, the fact that id
outputs the same integer value for both None
and my_None
means they are, in fact, the same object.
Note: The actual value produced by id
will vary across systems, and even between program executions. Under CPython, the most popular Python runtime, id()
does its job by reporting the memory address of an object. Two objects that live at the same memory address are the same object.
If you try to assign to None
, then you’ll get a SyntaxError
:
>>> None = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SyntaxError: can't assign to keyword
>>> None.age = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'age'
>>> setattr(None, 'age', 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'age'
>>> setattr(type(None), 'age', 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'NoneType'
All the examples above show that you can’t modify None
or NoneType
. They are true constants.
You can’t subclass NoneType
, either:
>>> class MyNoneType(type(None)):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type 'NoneType' is not an acceptable base type
This traceback shows that the interpreter won’t let you make a new class that inherits from type(None)
.
Conclusion
None
is a powerful tool in the Python toolbox. Like True
and False
, None
is an immutable keyword. As the null
in Python, you use it to mark missing values and results, and even default parameters where it’s a much better choice than mutable types.
Now you can:
- Test for
None
withis
andis not
- Choose when
None
is a valid value in your code - Use
None
and its alternatives as default parameters - Decipher
None
andNoneType
in your tracebacks - Use
None
andOptional
in type hints
How do you use the null
in Python? Leave a comment down in the comments section below!
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python's None: Null in Python