Why it matters
Calling an attribute or a method on None is the error Python programmers meet most often. The question "what is the difference between == and is?" is one of the most common Python interview questions. Both problems come from the same idea: a name points at an object, and a name can point at nothing at all.
By the end of this lesson you will be able to predict when a line raises an error on None, write checks that cannot crash, explain why 100 and 1000 behave differently under is, and write __eq__ and __hash__ for your own class.
The first principle: a name may point to None
Lesson 1 showed that a name points at an object. A name can also point at no object. In Python, the word for "no object" is None. It is a real object with one value, and it is the only value of its type.
Think of a slip of paper. Most slips have a street address written on them. An empty slip has nothing written on it. It is still a slip, so you can hold it, copy it and look at it. If you try to walk to the address, there is no house to go to.
None is that empty slip. You can store it, pass it to a function and compare it with other things. What you cannot do is ask the object it points to for help, because there is no object.
If you know Java: None plays the role of null. The difference is that in Python every name can hold None. There are no primitive types that refuse it.
None: the empty slip
Here is the smallest program that shows None at work. Run it.
Type nothing into the Input box for this program.
value: None
caught: object of type 'NoneType' has no len()
caught: 'NoneType' object has no attribute 'upper'
0 NoneLook at each line in turn. s = None makes the slip empty. The line print("value:", s) works, because print turns None into the text None. Passing None to a function is allowed. The function only fails when it tries to use it.
The next block calls len(s). len asks the object for its length, but there is no object, so Python raises a TypeError. A TypeError means that an operation was applied to a value of the wrong type. The try and except block catches it, so the program can print a message and go on.
The next block calls s.upper(). The dot means "find this method on the object", and again there is no object. Python raises an AttributeError, which means that the object has no attribute with that name. Here the object is None, and None has no upper attribute.
The last line shows default values. A list of numbers that you fill with zeros holds zeros. A list of names that you fill with None holds None in each slot. Python does not choose a default for you. The value you write in each slot is the value that is there.
What the error message tells you
Python prints the error type, a short message and the line where it happened. Here is the uncaught version of the same mistake:
name = None
print(name.upper())The program prints this (your file path will differ):
Traceback (most recent call last):
File "/home/you/example.py", line 2, in <module>
print(name.upper())
^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'upper'Read the last line first. AttributeError is the type. 'NoneType' object says the value was None, because NoneType is the name of the type that None belongs to. has no attribute 'upper' names the operation that failed. The carets under the line point at the expression that failed.
When you see this message, find the operation first, then ask why the value in front of the dot is None. Usually an earlier line should have set the name, or a function returned None when you did not expect it.
Stay safe: checks that cannot crash
There are three common ways to use a value that might be None without crashing.
The first is to check before you use the value. The and operator reads its left side first. If that side is false, it stops at once and does not run the right side. You can use this to protect a method call.
if s is not None and len(s) > 3:
print("long text")If s is None, the check s is not None is false, so and stops, and len(s) never runs. The check uses is not, not !=. The next section explains why.
The second is to put a literal first when you compare. A literal is a value written directly in the code, such as "admin". A literal is never None. The == operator is safe on either side, because None == "admin" returns False and does not raise an error. The check below is safe for any value of role.
Type nothing into the Input box for this program.
admin -> True
guest -> False
None -> FalseThe third line of output is the case that would crash with role.lower() == "admin". The == comparison never calls a method on role, so it gives False for None without any error. The loop prints None in the third line because print turns the value into text, which shows that the slot was empty.
The third way is a helper function that checks for None for you. You can write one in two lines, and most of the time an explicit is None check is clearer.
Default values: what a new name holds
Knowing what a name or an attribute holds before you use it saves you from a lot of crashes. Here is the rule.
- A local name in a function must be assigned before you read it. Python checks this when the code runs. If you read it first, you get an
UnboundLocalError. - An attribute that you never set does not exist. Reading it raises an
AttributeError. The usual fix is to set every attribute in__init__, so every object starts with all of its attributes. - A list that you create with
[None] * 3holds threeNonevalues. The list exists, but none of its items do. - A dictionary returns
Nonefromd.get(key)when the key is missing. The direct formd[key]raises aKeyErrorinstead.
The list rule is the one that trips people up most. [None] * 5 makes five empty slots. It does not make five students. Each slot must be filled with Student(...) before you use it.
Where None comes from
Knowing where a None can come from is the first step to preventing it. In real programs, a value is often None for one of these reasons.
A lookup found nothing. dict.get returns None for a missing key. The re.match function from the standard library returns None when the text does not match the pattern. A search function that you write yourself can return None when it finds nothing.
A function has no return statement. A function that does not reach a return gives back None. This is a common mistake when you forget to write return.
An attribute was never set. An attribute that a constructor does not set, or sets to None on purpose, stays None until something changes it.
Data from outside is missing. A database row, a web form or a JSON file can leave a value out. Libraries that read such data often give None for a missing value, rather than an empty string.
There is a better habit than checking everywhere. When a function has nothing to return in a collection, return an empty list, not None. An empty list is safe to loop over, and its loop body simply does not run. A function that returns None for a list forces every caller to write an extra check, and one forgotten check causes a crash.
When a function must return one object and may have none, None is still a common answer. In that case, make the caller's check obvious. The next program does that. It searches a list and checks the answer before it uses it.
Type nothing into the Input box for this program.
Ravi: found, name is Ravi
Meena: not foundThe function returns None on purpose when no student matches. The caller stores the result in found and checks it with found is None before reading found.name. If the caller had skipped the check, the second pass through the loop would raise an AttributeError on the line that reads found.name. The check is cheap, and it turns a crash into an answer the program can print.
== asks about value, is asks about identity
Now the second big topic. The == operator asks whether two objects are equal. The is operator asks whether two names point at the very same object, which is called identity.
For many built-in types, equal and identical mean different things. Two separate lists with the same items are equal, but they are not the same object. The == operator calls the object's __eq__ method to decide. The is operator only compares the identity, which you can see with id(). The id value is a number that is unique for each object while it lives, and it changes from one run to the next.
This pair of ideas makes a clean table:
| Question | Operator | What it compares |
|---|---|---|
| Are these the same value? (numbers, text, lists) | == | the content, as the class defines it |
| Are these the same object? | is | the identity, which is the same as id(a) == id(b) |
Is this value None? | is None | the identity, because None is a single object |
Here is the classic example. It creates two lists that hold the same items.
Type nothing into the Input box for this program.
True
False
TrueWalk through it. a and b point at two different lists with the same items. a == b compares the contents, so it is True. a is b compares the identities, which are different, so it is False. The name c points at the same list as a, so c is a is True.
The rule for None follows from this. None is a single object, so x is None asks the exact question you want. Use is None and is not None, not == None. A class can define __eq__ so that it returns True when compared with None, and then == None gives the wrong answer. is cannot be fooled that way.
Small integers are shared
CPython, the usual Python interpreter, keeps shared objects for the integers from -5 to 256. Every time a calculation produces one of those numbers, it reuses the shared object. Other integers are made new each time they are created.
This means two numbers can be equal under == and still be different objects under is, or the reverse, depending on their size. Here is the test. The function int() turns text into a number at run time, so each call makes a new object.
Type nothing into the Input box for this program.
True True
False TrueThe value 100 is in the shared range, so both names point at one object, and is is True. The value 1000 is outside the range, so each int("1000") makes a new object, and is is False. In both cases == is True, because the values are equal.
The lesson is simple: never use is to compare numbers. Use ==. The shared range is a detail of CPython, and a different Python implementation can change it. A program that depends on it can pass a quick test and then fail on other data. The same rule protects you from a bug that appears only for some values, which is the worst kind to find in testing.
Strings and identity
Text has the same trap, with a different range. CPython shares some string literals that are written in the same file. It also shares one-character strings made at run time. Other strings are new objects.
Type nothing into the Input box for this program.
True
False TrueThe two literals "dog" are the same object, so x is y is True. The text in z is built at run time, so it is a different object with the same characters. x == z is True, and x is z is False.
Python warns about is used with a literal. For example, x is "dog" gives a SyntaxWarning, because the answer depends on the implementation. Compare strings with ==. This keeps the same rule as the list example: == asks about content, and is asks about identity.
Enums: is is the right tool
An enum is a type with a fixed list of named values, such as the days of the week or the sizes of a drink. The enum module creates each name as a single object, once. So for an enum, is is correct and safe, and it is the style Python programmers expect.
Type nothing into the Input box for this program.
True
True
FalseThere is only one Size.MEDIUM object, so is and == agree. The check s is None is safe even when s holds an enum value. Both is and == are safe here, and is is the clearer choice when you mean "this exact member".
Your own eq and hash
If you write your own class and do not define __eq__, the comparison falls back to identity. Two objects with the same attributes are then not equal. To compare by content, you define __eq__. The method receives the other object, and it returns True or False.
Dictionaries and sets need a second method. Each object that goes in a set or is used as a dictionary key needs a hash value, which is a number computed from the object. The method __hash__ returns it. Sets and dictionaries use the hash value to decide where to look. The rule is simple: two objects that are equal must have the same hash value. Otherwise the set looks in the wrong place and does not find an object that is in it.
A complete Point class with two attributes looks like this:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
if self is other:
return True
if not isinstance(other, Point):
return NotImplemented
return self.x == other.x and self.y == other.y
def __hash__(self):
return hash((self.x, self.y))Read it line by line. self is other is a shortcut: if both names point at one object, they are equal. The isinstance check makes sure that other is a Point before the code reads its attributes. When the other object is a different type, the method returns NotImplemented. That tells Python to try the comparison from the other side, and if that side also gives up, Python returns False. This is why Point(1, 2) == None is False and does not raise an error. Then the method compares the attributes. The __hash__ method builds a tuple of the same two values and hashes it, so equal points get equal hash values.
Python has a shortcut for this pattern. The @dataclass(frozen=True) decorator writes __eq__ and __hash__ for you, based on the fields. A frozen dataclass cannot change after it is made, which is required for a safe hash value. The explicit version above shows what the shortcut does.
Here is a complete program. It uses a set of Point objects, and it relies on both methods.
Type nothing into the Input box for this program.
size = 2
contains (1,2)? True
True
FalseThe set has two elements, not three, because the second Point(1, 2) is equal to the first and the set does not store duplicates. in finds the point even though it is a brand-new object, because __hash__ sends it to the same slot and __eq__ confirms the match. The last line uses is on two new objects, so it is False.
A dictionary and a set work in two stages. First, the hash value chooses a slot. Then Python compares the key with the objects in that slot using __eq__. If the hash value is wrong, the first step sends the lookup to the wrong slot, and the second step never gets a chance to find the match.
Now the risk of skipping __hash__. When a class defines __eq__ in its body, Python sets its __hash__ to None unless you define one. Python then refuses to put the object in a set. The error is loud, which is better than a silent bug:
class Bare:
def __init__(self, x):
self.x = x
def __eq__(self, other):
return self.x == other.x
print({Bare(1)})The program prints this:
Traceback (most recent call last):
File "/home/you/example.py", line 8, in <module>
print({Bare(1)})
^^^^^^^^^
TypeError: cannot use 'Bare' as a set element (unhashable type: 'Bare')Define __hash__ together with __eq__, or do not define either. The two methods must agree about which attributes make two objects equal.
What eq must promise
Python does not check your __eq__ method against any rules, so you must follow them yourself. These are the promises that every correct equality method keeps. Interviewers often ask for them by name.
- Reflexive. An object equals itself.
p == pisTruefor anyp. - Symmetric. If
a == bisTrue, thenb == aisTrue. - Transitive. If
a == bandb == care bothTrue, thena == cisTrue. - Consistent. Repeated calls return the same answer while the objects do not change.
- Null-safe.
p == NonereturnsFalseand never raises an error.
A class that breaks one of these promises causes strange bugs in lists, sets and dictionaries. The most common break is symmetry, which happens when a subclass adds an attribute and compares with its parent in only one direction. The isinstance check and the NotImplemented return in the Point example keep the promises for a simple class. The None case works because isinstance(None, Point) is False, so the method returns NotImplemented, and Python then gives False.
A good way to test your __eq__ is to write a few small checks. Create two equal objects, two different ones and one None, then check each promise on them. The check takes a minute and catches most mistakes before they reach a set.
Type nothing into the Input box for this program.
reflexive: True
symmetric: True
transitive: True
different: False
null-safe: True
hash agrees: TrueEach line checks one promise. The symmetry line compares the answer of a == b with the answer of b == a, and the two must match. The transitivity line needs three objects that are all equal, so it uses c as the third. The different line must print False, because the points are not equal. An __eq__ that always returned True would fail it. The last line checks the link with __hash__: equal objects must have equal hash values.
Test your own classes in the same way. A check that prints False on any line tells you exactly which promise is broken.
Two names, one object
Lesson 1 introduced aliasing in passing. Here it is in full. Aliasing means that two or more names point at the same object. Each name is an alias for the object.
Take this as a rule. If two names point at one object, a change through either name is visible through both. The program below prints the result of that rule.
Type nothing into the Input box for this program.
50
TrueThis is aliasing, and it is the root of many "spooky" bugs. A function that stores a reference to an object in a list, and later the caller changes the object, leaves the list changed too. The fix is to decide, on purpose, whether the sharing is intended. Lesson 3 covers the rules for passing objects into functions, and lesson 4 covers copying.
Worked example: reading words, with missing values
The next program reads input and handles missing values with None. The first line of input is a count. The second line holds words separated by spaces. The word - means that the value is missing. The program must print the length of each word, or missing if the value is None.
count = int(input())
words = input().split()
for i in range(count):
word = words[i]
if word == "-":
word = None
if word is None:
print("missing")
else:
print(len(word))This program reads from the terminal, so it is not in a run block. To try it, save the file and run python3 on it. When the program asks for input, type the following two lines and press Enter after each one:
4
hello - a listThe output is:
5
missing
1
4The program reads the count with int(input()), then reads the words with input().split(). The split method breaks a line into words at the spaces. When the word is -, the program stores None in the name. Then is None checks for the missing value. Compare with None using is or is not, not ==, because is checks identity and cannot be fooled by a class that defines its own equality.
Chains of attributes
Real code rarely reads one name. It reads a chain, such as order.customer.address.city. Each dot follows one reference to the next object. The chain is only as safe as its weakest link. If any link is None, the whole expression fails at that point.
Here is a program with a chain where the customer attribute was never set.
class Address:
city = "Pune"
class Customer:
address = None
class Order:
customer = None
order = Order()
print("ready")
print(order.customer.address.city)The output is:
ready
Traceback (most recent call last):
File "/home/you/example.py", line 12, in <module>
print(order.customer.address.city)
^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'address'The message says that the value in front of .address is None. That value is order.customer. The program printed ready first, so the failure happened on the line that reads the chain, not earlier. The caret line shows where the chain stopped.
There are three ways to handle a chain. The first is to check each link, which is safe but long. The second is to set every link when you build the object, so that the chain never has an empty link. The third is to return a default, for example with getattr(order.customer, "address", None). This returns None when the attribute is missing, instead of raising an error. For a beginner, the first two are enough. The rule to remember is that every dot after the first one is a place where None can appear.
Comparing text in practice
Most text comparisons in real code are ==, but two more cases come up often. The first is case. The method casefold() changes text into a form for comparing it without regard to upper and lower case. The second is whitespace, where a value like " admin " should match "admin" after you remove the spaces with strip().
Both methods are called on the text, so they raise an error when the value is None. The strip() call on None raises an AttributeError, because strip is looked up on the value first. So the order matters: check for None, then call strip(), then compare. For example, s is not None and s.strip().casefold() == "admin" is safe in every case.
When a comparison needs to be exact, use ==. When a user types a value, you often want casefold() after strip(), because people type capitals and spaces inconsistently. Choose on purpose, and write the choice in a comment.
Debugging: a set that drops items
A developer writes a Book class with an __eq__ method that compares titles, and stores books in a set. The code looks like this:
class Book:
def __init__(self, title):
self.title = title
def __eq__(self, other):
return isinstance(other, Book) and self.title == other.title
shelf = set()
shelf.add(Book("Dune"))Running it raises an error, so the developer does not lose items silently. Work through the error in the same four steps.
Step 1: read the message. The last line says TypeError: cannot use 'Book' as a set element (unhashable type: 'Book'). The word unhashable is the key.
Step 2: check the rule. A set finds an object in two stages. First it computes the hash value and uses it to choose a slot. Then it compares with __eq__ inside that slot. This class defines __eq__ but not __hash__, so Python has set __hash__ to None. The object has no hash value at all.
Step 3: find the cause. The developer changed the rule for equality, but did not give the class a way to choose a slot. Without a hash value, the set cannot store the object.
Step 4: fix it. Add __hash__ with the same attribute that __eq__ uses. Put it inside the Book class, after __eq__:
class Book:
def __init__(self, title):
self.title = title
def __eq__(self, other):
return isinstance(other, Book) and self.title == other.title
def __hash__(self):
return hash(self.title)Now equal books share a slot, and the set can store them. The lesson is that __eq__ and __hash__ must be written as a pair. Python makes the mistake loud, but a class that defines both incorrectly, for example by hashing the object's id, will still lose items. Use only the attributes that decide equality in both methods.
Debugging walkthrough: a login check that fails for some users
A team member reports that the admin page crashes for some users, but not for others. The code looks like this:
roles = ["admin", None]
for role in roles:
print(role.lower() == "admin")Follow the four steps.
Step 1: read the message. Run the program and copy the last line of the error. In this case, it is AttributeError: 'NoneType' object has no attribute 'lower'. The operation is lower.
Step 2: find the empty value. The traceback shows the line print(role.lower() == "admin"). The value in front of .lower is role, and in the second pass of the loop, role is None.
Step 3: ask why the value is empty. The list was written with a None in it. In a real program, that None might come from a missing database column or a function that returned nothing.
Step 4: pick the fix. The code should not depend on the role being present. Put the literal on the left side of ==. The program then prints False for the missing role without crashing.
Type nothing into the Input box for this program.
True
False
2The lesson is to ask why a value is empty, before you add a None check everywhere. Often the real fix is one line earlier, where the value should have been set. Whether the missing role should be a False answer or an error is a decision for the business rules, but the crash is never the right answer.
Variations and edge cases
None as a dictionary key. A dictionary accepts None as a key. It is rarely a good idea, but it works, and d[None] returns the value stored under it.
None in concatenation. Python does not join text with None silently. "a" + None raises a TypeError. Use str(None) or an f-string if you want the word None in your output. The f-string f"value: {x}" writes None when x is None.
None in arithmetic and comparisons. None + 1 raises a TypeError, and so does None < 1. Python does not treat None as zero. Check for None before you do arithmetic on a value that might be missing.
Equal does not always mean identical for lists. [1, 2] == [1, 2] is True, but the two lists are different objects. Use is only when you want to know whether two names share one object.
Interview questions on this topic
"What is the difference between == and is?" == asks whether two objects are equal, which depends on __eq__. is asks whether two names point at the same object. Give the example of two separate lists with the same items.
"Why does a is b give True for 100 but False for 1000?" CPython keeps shared integer objects for the range -5 to 256 and reuses them. Other values create new objects, so is compares two different identities. Both comparisons with == are True.
"What must you do when you define __eq__?" Define __hash__ too, so that equal objects have equal hash values. Otherwise Python sets __hash__ to None, and the object cannot go in a set or be a dictionary key.
"How do you avoid an error when a value might be None?" Check with is not None before you use it, or put a literal on the left of == when you compare.
"What promises must an __eq__ method keep?" It must be reflexive, symmetric, transitive, consistent and null-safe. Name at least three, and say which one a subclass most often breaks.
"Why should an enum member be compared with is?" Each enum member is one object, so identity is the same as equality. is is clear, and it never raises an error.
Follow-up you should expect: "What does None == None give, and why?" It gives True, because None is one object and it is equal to itself. Use is None for the check anyway, because it asks about identity and does not depend on any __eq__ method.
Real-world uses
Web forms and JSON files often send missing fields as None or as null, which Python reads as None. Code that reads a field and calls a method on it crashes on the first empty form. Checking with is None first, or putting the literal first in a comparison, is the standard guard in production code.
Sets and dictionaries are everywhere: caches, deduplication, sets of user IDs and routing tables. Any class you put in one of them needs correct __eq__ and __hash__. Many bugs of the form "the item is in the list but the lookup says no" come from an __eq__ that compares different fields than the code expects.
Database libraries return None for a NULL column. The program must check before it does arithmetic on the value. Many teams convert missing values to a default at the boundary of the program, so that None does not spread into the rest of the code.
Practice
Predict each answer before you run anything. Write the answer on paper first.
- What does this print?
x = None; print(x + "!") - Write
__eq__and__hash__for aStudentclass with one attributeid. Two students with the same id should be equal. - Why does
[0] * 3hold zeros, while[None] * 3holdsNonein each slot? Explain in two sentences. - What does this print?
a = "dog"; b = "dog"; print(a is b)Then change the second line tob = "".join(["d", "og"])and predict again. - Write a function
describe(s)that returns"empty"whensisNone, and otherwise returns"length " + str(len(s)). - Write a function
safe_get(d, key)that returns the stored value, or 0 when the key is missing. - Explain why Python allows
x = Nonefor any name, and what a name that holdsNonecannot do. - A class
Pointhas no__eq__. The statementPoint(1, 2) in [Point(1, 2)]printsFalse. Why, and what fixes it? - Write a
Pointclass with__eq__and__hash__, then put three points in a set, two of which are equal. What size does the set have? - Read this code and say what it prints:
a = int("100"); b = int("100"); c = int("1000"); d = int("1000"); print(a is b, c is d, c == d)
Show the answer
-
It raises
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'. Python does not joinNonewith text. Usestr(x)or an f-string if you want the wordNonein the output. -
One possible answer:
class Student:
def __init__(self, id):
self.id = id
def __eq__(self, other):
if self is other:
return True
if not isinstance(other, Student):
return NotImplemented
return self.id == other.id
def __hash__(self):
return hash(self.id)-
You choose the value that goes in each slot.
[0] * 3repeats the number 0, and[None] * 3repeats the valueNone. Python lists have no default type, so the value you write is the value that is stored. -
The first version prints
True, because two identical string literals in the same file are shared. The second version printsFalse, because"".joinbuilds a new string at run time, so the two names point at different objects. -
One possible answer:
def describe(s):
if s is None:
return "empty"
return "length " + str(len(s))- One possible answer:
def safe_get(d, key):
return d.get(key, 0)The method dict.get returns the second argument when the key is missing. Written out, it is the same as checking key in d first.
-
Python names have no declared types. Every name points at an object, and
Noneis an object, so any name can hold it. A name that holdsNonecannot be used for anything that needs an object, such as reading an attribute or calling a method, until it is given a real value. -
The
inoperator compares with==. Without an__eq__method,==falls back to identity, so two separatePointobjects are never equal, even with the same numbers. The fix is to define__eq__on the class, and__hash__as well if the points go in a set. -
The set has size 2. The two equal points count as one element, and the third point is a second element.
-
It prints
True False True. The value 100 is in the shared range, soa is bisTrue. The value 1000 is not, soc is disFalse.c == dcompares the values, so it isTrue.
What you now know
Noneis an empty reference. Reading an attribute or calling a method on it raisesAttributeError, and using it as a value in an operation raisesTypeError.- Check with
is Nonebefore you use a value that might be missing, or put a literal on the left of==. ==asks whether two objects are equal, which depends on__eq__.isasks whether two names point at the same object.- Small integers and some strings are shared in CPython, so never use
isto compare numbers or text. - If you define
__eq__, define__hash__too, so that sets and dictionaries work. - Two names can point at one object. A change through one is visible through the other.