The problem
Tuples are immutable sequences in Python. One common way to create a tuple is to put comma separated values in between parentheses.
some_tuple = (1, 2, 3)
There are a few circumstances where you might prefer an immutable sequence over a mutable one, like a list. One reason they can be useful is for holding the arguments to a function.
Let’s say you want to write a threaded function that prints its argument every second for 10 seconds. You might do something like the following:
import time
import threading
def print_forever(some_value):
for _ in range(10):
print(some_value)
time.sleep(1)
args_tuple = (1)
thread = threading.Thread(target=print_forever, args=args_tuple)
But this example is wrong in a subtle way and throws an exception.
>>> thread.start()
Exception in thread Thread-65:
Traceback (most recent call last):
File "/Users/jbencook/anaconda3/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/Users/jbencook/anaconda3/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
TypeError: print_forever() argument after * must be an iterable, not int
The fix
In the above example, args_tuple
isn’t really a tuple. To fix it, you need to change that line.
args_tuple = (1,)
The reason
Why would Python do this? One reason is that parentheses allow you to write multi-line statements without the annoying backslash as a line-continuation character.
this_is_valid = (
2 +
2
)
print(this_is_valid)
For strings, you’re not even required to have the plus operator.
important_message = (
"hello "
"world"
)
>>> print(important_message)
hello world
While this is tremendously useful for writing concise code, it means that when you actually want a 1-element tuple, you need to add a comma after the first value.
this_is_a_tuple = (4,)