Fundamentals 8 min read

When to Use [] vs list() in Python: Performance, Readability, and Pitfalls

This article compares Python's literal [] and the list() constructor, examining their speed differences, readability implications, default‑argument pitfalls, object identity, and appropriate use cases such as creating empty lists, converting iterables, and avoiding mutable default parameters.

Code Mala Tang
Code Mala Tang
Code Mala Tang
When to Use [] vs list() in Python: Performance, Readability, and Pitfalls

Fundamentals: [] vs list()

At first glance, both ways can create an empty list:

a = []
b = list()
print(a == b)  # True

So far, everything works, but differences start to appear later.

Performance: Speed matters

In Python, the literal [] syntax is actually faster than calling list().

Performance test

import timeit
print(timeit.timeit('[]', number=1000000))
print(timeit.timeit('list()', number=1000000))

On most machines, [] runs faster. Why? Because [] is a literal parsed directly by the interpreter, while list() is a function call that incurs extra overhead.

[] is a literal – it is parsed directly by the Python interpreter. list() is a function call – and function calls in Python add overhead.

If you care about micro‑optimizations (e.g., in tight loops), prefer [] over list().

Readability and intent

Sometimes the choice is about clarity rather than performance.

Consider the following code:

usernames = list()  # Looks like you are creating an empty list

vs: usernames = [] Many Python developers find [] more concise and "Pythonic". However, when you need to convert another iterable, list() becomes necessary: list('hello') # ['h', 'e', 'l', 'l', 'o'] So the decision is context‑dependent.

Function default value: [] trap

Let's talk about mutable default arguments – a common beginner pitfall in Python.

Wrong way

def append_item(item, lst=[]):
    lst.append(item)
    return lst

You might expect a new list each call, but the same list object is reused:

print(append_item('a'))  # ['a']
print(append_item('b'))  # ['a', 'b']

Correct way

def append_item(item, lst=None):
    if lst is None:
        lst = list()  # or lst = []
    lst.append(item)
    return lst

Because the default [] is evaluated only once at function definition time, using list() (or []) inside the function avoids the shared‑state trap.

Flexibility: list() can take arguments

Unlike [], list() can convert other iterables into a list:

list(range(3))          # [0, 1, 2]
list((1, 2, 3))        # [1, 2, 3]
list({1, 2, 3})        # [1, 2, 3]
list(map(str, [1, 2]))  # ['1', '2']

Trying the same with [] results in a TypeError: []( 'abc' ) # TypeError Therefore, list() is superior for data conversion.

Mutability is the same

Both creations produce mutable lists:

a = []
b = list()
a.append(1)
b.append(2)
print(a)  # [1]
print(b)  # [2]

Once created, their behavior is identical; the difference lies in how you create them.

Object identity: not always the same

a = []
b = []
print(a is b)  # False

Each call to [] or list() returns a new object – no shared references.

[] == []   # True
[] is []    # False

Equality checks values, identity checks memory addresses; keep this distinction in mind when using is and ==.

When to use []

Creating an empty list (performance advantage).

Better readability and conciseness.

Initializing new lists inside loops or functions.

Generally as the default constructor.

results = []

When to use list()

Converting other iterables to a list.

Avoiding mutable default argument pitfalls (inside functions).

Explicitly expressing intent during data transformation.

Creating lists from generators or map objects.

names = list(map(str.upper, ['alice', 'bob']))

Real case: list initialization in loops

This is a subtle but practical situation – initializing lists inside a loop.

Don't do this

output = []
for _ in range(3):
    output.append([])

Looks fine, but consider:

output = [[]] * 3
output[0].append(1)
print(output)  # [[1], [1], [1]]

The [] * 3 replicates the same list object, causing all entries to share modifications.

A better approach: output = [list() for _ in range(3)] or: output = [[] for _ in range(3)] This creates three independent lists.

Summary

In Python, [] and list() both create empty lists, but they differ significantly in performance, readability, flexibility, and object identity. In most cases, [] is the preferred way to create an empty list because it is shorter, faster, and idiomatic. However, list() is essential when converting other iterables to a list and when avoiding mutable default argument pitfalls inside functions. Understanding these differences helps you write more efficient and reliable Python code.

PerformancePythonlistreadabilitydefault-arguments
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.