This rule raises an issue when several elements are added to the same list through consecutive append() calls, either as a sequence of
statements or through a for-loop.
Adding elements to a list one at a time is unnecessary when the extend() method exists. This happens with a sequence of
append() statements:
my_list.append(first) my_list.append(second) my_list.append(third)
It also happens when a for-loop appends every element of another collection, which is the same sequence of calls spread over an iteration:
for element in other_collection:
my_list.append(element)
The extend() method combines all additions into a single call and avoids the overhead of repeated append()
invocations:
my_list.extend([first, second, third]) my_list.extend(other_collection)
Grouping the additions makes the intent explicit: the reader sees one operation that grows the list instead of a series of independent statements. It also removes redundant call overhead, since the attribute lookup and the method call are resolved once instead of once per element. In hot code or when the source collection is large, the difference becomes measurable.
No issue is raised when other statements are interleaved between the append() calls, or when the body of the loop does more than
append the loop variable, for example when it filters or transforms the elements:
for element in other_collection:
if element.is_valid():
my_list.append(element)
Group the appended elements into a single extend() call. For consecutive statements, pass the elements as a list literal. For a loop,
pass the iterated collection directly, as extend() accepts any iterable.
def build_command(base_command, path):
command = list(base_command)
command.append("--archive") # Noncompliant
command.append("--verbose")
command.append(path)
return command
def build_command(base_command, path):
command = list(base_command)
command.extend(["--archive", "--verbose", path])
return command
def collect_results(results, new_results):
for result in new_results:
results.append(result) # Noncompliant
return results
def collect_results(results, new_results):
results.extend(new_results)
return results
extend() iterates over its argument and appends every element to the list, so the result is exactly the same as the individual calls.
The augmented assignment my_list += [first, second, third] is equivalent to extend() and can be used instead when it reads
better.
Do not confuse extend() with append(): my_list.append(other_collection) adds the collection itself as a
single element, while extend() adds its elements.
A loop that appends to the list it iterates over never terminates, while my_list.extend(my_list) simply doubles the list. The fix is
behavior-preserving in every other case, so make sure the loop you replace iterates over a different collection.
list.extend() methodlist, tuple, range