Skip to content
VLSI Mentor

Python Part I · Module 6 · Tuples

The One-Item Tuple Trap

This is the shortest idea in the module and it has its own chapter for a reason: it catches essentially everyone exactly once, and when it does, nothing raises. A tuple with one element needs a trailing comma, and a pair of parentheses with one thing inside them is not a tuple at all — it is just that thing. Stated as a rule that sounds like trivia. The reason it matters is that one real Python operation you have already used takes a group of options, and writing that group with one option and no comma does not produce an error. It produces a different, perfectly plausible, wrong answer.

Foundation10 min readPythonPart IFundamentalsTuplesSyntax

Part I · Module 6 · Chapter 6.2 · The One-Item Tuple Trap

1. The Trap

Here it is, in four lines:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
not_a_tuple = (5)
print(not_a_tuple)
print(type(not_a_tuple))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
5
<class 'int'>

Parentheses, one value inside, and the result is an int. Not a tuple of one element — the number five.

Now with one character added:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
real_tuple = (5,)
print(real_tuple)
print(type(real_tuple))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
(5,)
<class 'tuple'>

A trailing comma, and it is a tuple. Python even prints it back with the comma still there, which is its way of telling you this is a one-element tuple and not a number in brackets.

2. Why This Is the Only Possible Answer

If you learned Chapter 6.1's rule, this is not something to memorise — it follows.

The comma makes the tuple. The parentheses group.

So in (5) there is no comma, which means there is no tuple. The parentheses are doing what parentheses have done since Chapter 3.8: grouping an expression. (5) is five for exactly the reason (2 + 3) is five — brackets round a single value change nothing about it.

And in (5,) there is a comma, so there is a tuple, with one element.

The parentheses are not even required:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
also = 5,
print(also, type(also))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
(5,) <class 'tuple'>

A bare 5, is a one-element tuple. That looks like a typo and is valid Python — which is itself a decent argument for keeping the parentheses as a visual signal, even though they are not what creates the tuple.

3. The Same Trap With Any Type

Nothing about this is specific to numbers:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
s = ("PASS")
t = ("PASS",)
print(type(s), len(s))
print(type(t), len(t))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
<class 'str'> 4
<class 'tuple'> 1

("PASS") is the string "PASS" — four characters. ("PASS",) is a tuple holding one string — one element.

Look at what len() did there, because it is the fastest diagnostic you have:

4. Two or More Need Nothing Special

The trailing comma is only load-bearing for one element. From two upwards the commas between the elements already do the work:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
two = (5, 6)
print(two, type(two), len(two))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
(5, 6) <class 'tuple'> 2

You may still put a trailing comma on a longer tuple, and it is harmless:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
three = (1, 2, 3,)
print(three, len(three))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
(1, 2, 3) 3

Three elements, not four — a trailing comma never adds an empty element. This is the same convention Chapter 5.7 recommended for multi-line list literals, where a trailing comma makes adding a line a one-line change.

5. Where It Actually Bites

Everything so far is a type() curiosity. Here is the case that makes this chapter worth its own page, and it is a real bug shape.

Chapter 4.10 showed endswith accepting several alternatives grouped together — and Chapter 6.1 noted that the group is a tuple. Checking a file against two extensions works like this:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("top.sv".endswith((".sv", ".v")))
print("top.v".endswith((".sv", ".v")))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
True
True

Both match, which is what you wanted. Now suppose the requirement narrows to one extension and somebody edits the line down, dropping the now-lonely comma:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE — no error, wrong answer
print("top.sv".endswith((".v")))
print("top.v".endswith((".v")))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
False
True

No error. The code runs, returns booleans, and quietly stops matching .sv files — because (".v") is not a one-option group, it is the plain string ".v", and "top.sv" does not end with ".v".

Written correctly, with the comma:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("top.sv".endswith((".v",)))
print("top.v".endswith((".v",)))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
False
True

The same two results — because in this instance one option really was intended. The point is not that the corrected version differs here; it is that you cannot tell from the output which version you wrote. One of them means "any of these options" and the other means "this exact string", and they coincide often enough that the mistake survives testing.

6. Two Failures That Do Raise

Not every version of this mistake is silent. When the non-tuple is then used as a tuple, Python objects.

Concatenating:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
print((1, 2) + (3))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: can only concatenate tuple (not "int") to tuple

That message is the same shape Chapter 4.3 and Chapter 5.6 showed for strings and lists. The author meant (3,):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print((1, 2) + (3,))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
(1, 2, 3)

Indexing:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
x = (5)
print(x[0])
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: 'int' object is not subscriptable

x is the number five, and a number has no positions to index. Subscriptable is Python's word for "supports the square-bracket operation" — strings, lists and tuples are; numbers are not.

These two are the lucky cases: they fail immediately and point at the line. The endswith case in Section 5 is the unlucky one.

7. Predict, Run, Observe

Predict the type and length of each before reading on. Two of these raise on the length.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(type((7)))
print(type((7,)))
print(type(("x")))
print(type(("x",)))
print(len((7,)))
print(len(("x")))
print(len((7, 8)))
print(len(()))

The verified output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
<class 'int'>
<class 'tuple'>
<class 'str'>
<class 'tuple'>
1
1
2
0

Nothing raised after all — and the sixth line is the one to look at. len(("x")) is 1, because ("x") is the one-character string "x", whose length is 1. It gives the same answer a one-element tuple would, for a completely different reason.

That is the chapter in one line: the answer looking right is not evidence that the value is right. If you need certainty, check the type, not the length.

8. Exercises

Exercise 1 — type them all. Without running anything, give the type of each, then verify: (a) (9) (b) (9,) (c) 9, (d) () (e) ("a", "b") (f) ("a",) (g) ("a")

Exercise 2 — fix the record. A colleague wants a tuple holding one signal name and writes sig = ("clk"). Say what they actually have, what len(sig) returns and why that is misleading, and give the corrected line.

Exercise 3 — predict then verify. Run each and write down the exact result. One raises; name the error and explain it in one sentence:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print((1, 2) + (3,))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print((1, 2) + (3))

Exercise 4 — the silent one. Explain in three sentences why path.endswith((".v")) does not raise, what it actually checks, and how it differs from path.endswith((".v",)).

Exercise 5 — detect it. You are handed a name group and told it is a group of file extensions. Write the two lines you would run to find out whether it really is, and say what each would show if somebody had forgotten the comma.

Exercise 6 — trailing commas. Predict len((1, 2, 3,)), then verify, and say in one sentence why the trailing comma does not add an element.

Exercise 7 — explain the rule. In two sentences, explain why (5) is not a tuple, referring to what the parentheses are actually doing. Do not use the word "exception".

9. Summary

  • (5) is the number five. Parentheses around a single value group it; they do not create a tuple.
  • (5,) is a tuple of one element. The trailing comma is what creates it.
  • This is not a special rule — it is Chapter 6.1's rule applied to one element: the comma makes the tuple.
  • The parentheses are optional even here. 5, is a one-element tuple.
  • len() is the fastest diagnostic, but it is not conclusive: len(("x")) is also 1, because the string has one character.
  • Check the type when you need certainty.
  • Two elements and up need no trailing comma, and a trailing comma on a longer tuple adds nothing.
  • The dangerous case is a one-option group. endswith((".v")) is a plain string, not a group, and it silently checks something different. No error is possible, because the expression is valid.
  • (1, 2) + (3) raises TypeError: can only concatenate tuple (not "int") to tuple, and (5)[0] raises TypeError: 'int' object is not subscriptable.

The next chapter reaches into a tuple, using position rules you already know.

Where this fits

Part of the Python curriculum.