Guide Python Intermediate

7.13 Operators with Different Data Types

How + and * change meaning across numbers, strings, lists, tuples, sets, and dicts — concatenation, repetition, union, intersection, and dict merging.

2 min read

Several operators behave completely differently depending on the operand type — + means numeric addition for numbers, but concatenation for sequences. Knowing these per-type behaviors avoids surprises.

Numbers

>>> 5 + 3
8

Strings

+ concatenates; * repeats.

>>> "a" + "b"
'ab'
>>> "ab" * 3
'ababab'

Lists

+ concatenates two lists into a new one; * repeats a list’s elements. See 5.4 Sequence Data Types.

>>> [1, 2] + [3, 4]
[1, 2, 3, 4]
>>> [1, 2] * 2
[1, 2, 1, 2]

Tuples

Same + and * behavior as lists, but the result is always a new tuple, since tuples are immutable — see 5.9 Mutable vs Immutable Types.

>>> (1, 2) + (3, 4)
(1, 2, 3, 4)

Sets

Sets repurpose | and & for union and intersection respectively — a different meaning than their bitwise use on integers (see 7.6 Bitwise Operators), but a natural fit conceptually. See 5.6 Set Data Types.

>>> {1, 2} | {2, 3}     # union
{1, 2, 3}
>>> {1, 2} & {2, 3}     # intersection
{2}

Dictionaries

Python 3.9+ supports | for merging two dicts directly; the ** unpacking trick works on all Python 3 versions. See 5.5 Mapping Data Type.

>>> d1, d2 = {"a": 1}, {"b": 2}
>>> {**d1, **d2}      # merge via unpacking (works on any Python 3)
{'a': 1, 'b': 2}

Quick Interview Answer

“The same operator symbol can mean very different things depending on the operand type: + is numeric addition for numbers but concatenation for strings, lists, and tuples; * is multiplication for numbers but repetition for sequences. Sets repurpose | and & for union and intersection instead of their bitwise meaning on integers. Dicts support | for merging in Python 3.9+, or the {**d1, **d2} unpacking pattern on any Python 3 version — with later keys overriding earlier ones on conflicts.”

Common Mistakes

  • Expecting set1 + set2 to work like list concatenation — sets have no +; use | for union instead.
  • Forgetting {**d1, **d2} merge order matters — keys from d2 override matching keys from d1, not the other way around.
  • Using * to repeat a list of mutable objects (e.g. [[]] * 3) expecting three independent inner lists — it actually creates three references to the same inner list, a classic shared-reference bug (see 6.2 Objects and Variable References).

Add More Questions to This Guide

Know a question that should be here? Share it and help the community!

Open Google Form