In Python, to determine whether a list or tuple is empty, you can use three methods (since checking for lists and tuples is similar, we’ll use lists as an example). The three methods are: comparing with an empty list, checking the length of the list, and directly using an if
statement.
Python Implementation
#! env python
## Checking if a list is empty: 3 methods
### Method 1: Compare with an empty list
def compare_empty(a):
if a == []:
return True
return False
### Method 2: Check if the list length is 0
def compare_len(a):
if len(a) == 0:
return True
return False
### Method 3: Use if directly
def list_if(a):
if a:
return False
return True
In general, we recommend using the third method, as it leverages Python’s built-in capabilities and runs more efficiently. But why is that? How is it implemented internally in Python?
Internal Implementation of the Three Methods
Since Python is an interpreted language, the code is first compiled into bytecode and then executed by the interpreter. To understand the internal process, we use Python’s dis
module to view the bytecode. Below is the bytecode output for the three methods.
Comparing with an empty list
#! env python
import dis
def compare_empty(a):
if a == []:
return True
return False
dis.dis(compare_empty)
"""
In [7]: dis.dis(compare_empty)
2 0 LOAD_FAST 0 (a)
2 BUILD_LIST 0
4 COMPARE_OP 2 (==)
6 POP_JUMP_IF_FALSE 12
3 8 LOAD_CONST 1 (True)
10 RETURN_VALUE
4 >> 12 LOAD_CONST 2 (False)
14 RETURN_VALUE
"""
If you’re unfamiliar with dis
, it might seem complicated. On the left is the line number from the source code, and on the right is the bytecode that line compiles into. A single line of Python code usually corresponds to multiple bytecode instructions. Since the main difference between these methods lies in the if
condition, we only need to look at the bytecode for that line.
There are four steps in this method:
"""
2 0 LOAD_FAST 0 (a)
2 BUILD_LIST 0
4 COMPARE_OP 2 (==)
6 POP_JUMP_IF_FALSE 12
"""
LOAD_FAST
: Retrieve the variablea
from memory and place it on top of the stackBUILD_LIST
: Create a new empty list and place it on the stackCOMPARE_OP
: Compare the two items on the stackPOP_JUMP_IF_FALSE
: Pop the result and jump if it’s false
This is the slowest method, as it involves allocating memory for a new list and then comparing values, which adds overhead for garbage collection and execution time.
Checking if the length is 0
def compare_len(a):
if len(a) == 0:
return True
return False
dis.dis(compare_len)
"""
2 0 LOAD_GLOBAL 0 (len)
2 LOAD_FAST 0 (a)
4 CALL_FUNCTION 1
6 LOAD_CONST 1 (0)
8 COMPARE_OP 2 (==)
10 POP_JUMP_IF_FALSE 16
"""
This method involves six steps:
LOAD_GLOBAL
: Load thelen
functionLOAD_FAST
: Retrieve the variablea
CALL_FUNCTION
: Call thelen
function witha
as the argumentLOAD_CONST
: Load the constant 0COMPARE_OP
: Compare length to 0POP_JUMP_IF_FALSE
: Branch based on result
It avoids iteration and is faster than the previous method.
Using if directly to check boolean value
def list_if(a):
if a:
return False
return True
dis.dis(list_if)
"""
2 0 LOAD_FAST 0 (a)
2 POP_JUMP_IF_FALSE 8
"""
This method only takes two steps:
LOAD_FAST
: Load variablea
POP_JUMP_IF_FALSE
: Evaluate the boolean value and jump accordingly
These two operations are present in the previous methods as well, making this the fastest approach.
Why does POP_JUMP_IF_FALSE
work directly? That’s because Python (implemented in C) checks the truthiness of objects: if the length is greater than 0, it returns true; otherwise, false. That’s how CPython helps Python code run more efficiently.
Summary
This article compares three methods for checking if a list or tuple is empty in Python. Using the dis
module, we examine their bytecode to understand how each method works internally.