Innovate | Connect | Transform
ContactService statusUSD $

GICT knowledge base

Creating an Updated Tuple in Python: Four Practical Methods

Published

Python

You cannot assign a new value to a tuple item. To represent an updated record, construct a new tuple and bind a variable to it. Existing references to the original tuple continue to see the original sequence. This guide covers replacement, extension, removal, and the separate case of changing a mutable object stored inside a tuple.

1. Replace an item through a temporary list

original = ("web.example", 443, "https")
items = list(original)
items[1] = 8443
updated = tuple(items)
assert original == ("web.example", 443, "https")
assert updated == ("web.example", 8443, "https")

This is useful when several positions need changing. It allocates a list and a new tuple; it is not an in-place tuple update. Both conversions are shallow, so nested mutable objects remain shared unless you explicitly copy them appropriately.

2. Replace one position with slices

original = (10, 20, 30, 40)
updated = original[:2] + (25,) + original[3:]
assert updated == (10, 20, 25, 40)
assert original == (10, 20, 30, 40)

The comma in (25,) creates a one-item tuple. Slices and concatenation build new sequences, so this is not a constant-time edit. A naive expression with an out-of-range index may append a value instead of raising an error. Validate an index when writing a reusable helper:

def replace_item(values, index, replacement):
    if not -len(values) <= index < len(values):
        raise IndexError("tuple index out of range")
    if index < 0:
        index += len(values)
    return values[:index] + (replacement,) + values[index + 1:]

assert replace_item((10, 20, 30), -1, 40) == (10, 20, 40)
for values, index in [((), 0), ((10, 20), 2), ((10, 20), -3)]:
    try:
        replace_item(values, index, 99)
    except IndexError:
        pass
    else:
        raise AssertionError("Expected an invalid-index error")

This helper expects a tuple and an integer index. If your application needs a broader interface, add input validation rather than silently converting arbitrary values.

3. Add or remove values by building a new tuple

ports = (80, 443)
extended = ports + (8443,)
without_first = ports[1:]
without_http = tuple(port for port in extended if port != 80)
assert extended == (80, 443, 8443)
assert without_first == (443,)
assert without_http == (443, 8443)
assert ports == (80, 443)

Filtering by value removes every matching value, not just one occurrence. A generator expression inside tuple(...) builds a tuple; parentheses around a comprehension by themselves produce a generator, not a tuple comprehension.

4. Unpack and rebuild a fixed record

endpoint = ("web.example", 443)
previous = endpoint
host, port = endpoint
endpoint = (host, 8443)
assert previous == ("web.example", 443)
assert endpoint == ("web.example", 8443)

Rebinding endpoint does not modify previous. For larger records, named fields can make an update less error-prone than positional unpacking.

Repetition is not an independent deep copy

events = []
records = (events,) * 2
records[0].append("started")
assert records[0] is records[1]
assert records == (["started"], ["started"])

Multiplication repeats references. This example contains the same list twice. Do not use it to create supposedly independent mutable records.

Mutable items and dictionary keys

record = ("web.example", [80])
record[1].append(443)
assert record == ("web.example", [80, 443])
try:
    hash(record)
except TypeError:
    print("A tuple containing a list is not hashable")

The tuple still points to the same objects, but the list’s contents changed. Tuples are therefore not a general security or deep-immutability mechanism. A tuple can be a dictionary key only when its items are hashable; see Python’s hashability definition.

Verification: All seven code blocks were executed with Python 3.12.14. Tests cover preserving the original tuple, negative indices, invalid indices, empty input, and shared mutable references. Choose the representation for clarity first, then measure your workload if allocation or speed matters. For the basic syntax, see Python Tuple Basics.

Related guides

Account services are unavailable until the production backend is configured.