Parentheses do not a tuple make

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 until the end of time. You might do something reasonable like the following:

from __future__ import print_function
import time
import threading

def print_forever(some_value):
  while True:
      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, throwing an exception:

>>> thread.start()
Traceback (most recent call last):
 File "/opt/conda/lib/python3.5/threading.py", line 914, in _bootstrap_inner
   self.run()
 File "/opt/conda/lib/python3.5/threading.py", line 862, 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 to:

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,)

Comments

comments powered by Disqus