A tuple is a sequence of values. The values can be any type, and they are indexed by integers, so in that respect, tuples are a lot like lists. The important difference though, is that tuples are immutable.

A tuple is a comma-separated list of values, with or without in parentheses:

>>> t = 'a', 'b', 'c', 'd', 'e'

which is the same as:

>>> t = ('a', 'b', 'c', 'd', 'e')

How can we create a tuple with a single element? One may try:

>>> t = ('a')
>>> type(t)
<type 'str'>

which is not what we wanted. A correct way is to put a final comma:

>>> t = ('a',)    # or equivalently, t = 'a',
>>> type(t)
<type 'tuple'>

To create an empty tuple, we can use the built-in function tuple():

>>> t = tuple()
>>> type(t)
<type 'tuple'>
>>> print t

If we include an argument in a form of a sequence (string, list or tuple) when using tuple, we get a tuple with the elements of the sequence.

For a string input:

>>> t='apple'
>>> print tuple(t)
('a', 'p', 'p', 'l', 'e')

For a list input:

>>> t=[1,2,3]
>>> print tuple(t)
(1, 2, 3)

For a tuple input:

>>> t='a','b','c'
>>> t1= tuple(t)
('a', 'b', 'c')
>>> print t1[0]
>>> t is t1
>>> id(t) == id(t1)

For a dictionary input, we only get key elements with no particular order:

>>> t={'one':'hana','two':'dool'}
>>> t1 = tuple(t)
>>> print t1
('two', 'one')
>>> t1[1]


In general, you can convert type A to type B by using any built-in function such as list, tuple, dict, str, float, int, etc.:

>>> B=list(A)
>>> B=tuple(A)
>>> B=str(A)

and so on.

Tuple assignments

We have seen this already, but let’s refresh our memory again. A tuple assignement is an elegant way to assign multiple values in a single line:

>>> a,b = 1,2

and we can also swap them:

>>> print a,b
1 2
>>> a, b = b, a
>>> print a,b
2 1

Tuples as return values

When we specify return values, we can also return multiple values:

>>> def min_max(t):
...     return min(t),max(t)

>>> t = [1,2,3]
>>> min_max(t)

>>> t={'one':'hana','two':'dool','three':'set'}
>>> t1=tuple(t)
>>> t1
('three', 'two', 'one')
>>> min_max(t1)
('one', 'two')

>>> min_max(t.values())
('dool', 'set')

Variable-length argument tuples

Functions can take a variable number of arguments. A parameter name that begins with * gathers arguments into a tuple. For instance, printall takes any number of arguments and prints all of them:

>>> def printall(*args):
...     print args

>>> printall(1,'a',159,{'one':'hana'})
(1, 'a', 159, {'one': 'hana'})

This special syntax, *args, is for any variable numbers of inputs that are non-keyworded, while **kwargs is for key-worded inputs.

An example with **kwargs as a function argument produces a dictionary as output:

>>> def printall(**kwargs):
...     print kwargs

>>> printall(key1=1,key2='a',key3=159,key4={'one':'hana'})
{'key3': 159, 'key2': 'a', 'key1': 1, 'key4': {'one': 'hana'}}

You will get an error if you specify an argument without a keyword, i.e., key=...:

>>> printall('ams209')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: printall() takes exactly 0 arguments (1 given)

See more examples here.

Lists and tuples, dictionaries and tuples

We can use the built-in function zip which takes two or more sequences to create a list of tuples where each tuple contains one element from each sequence. For example:

>>> s='abc'
>>> t=[0,1,2]
>>> z=zip(s,t)
>>> print z
[('a', 0), ('b', 1), ('c', 2)]

The result is a list of tuples where each tuple contains a character from the string s and the corresponding element from the list t.

Furthermore, we can convert the resulting list into a dictionary using dict:

>>> dict(z)
{'a': 1, 'c': 3, 'b': 2}

This is a concise way to create a dictionary combining zip and dict. Another example we can immediately think of is:

>>> e=['one','two','three']
>>> k=['hana','dool','set']
>>> eng2kor=zip(e,k)
>>> eng2kor
[('one', 'hana'), ('two', 'dool'), ('three', 'set')]
>>> eng2kor=dict(eng2kor)
{'three': 'set', 'two': 'dool', 'one': 'hana'}

One can also go in the other direction using items, i.e., you can use a dictionary to create a list of tuples. Continuing from the last execution:

>>> type(eng2kor)
<type 'dict'>
>>> eng2kor.items()
[('three', 'set'), ('two', 'dool'), ('one', 'hana')]
>>> type(eng2kor.items())
<type 'list'>

In case the sequences are not the same length, the result has the length of the shorter one:

>>> zip('ams','0123456789','$#@!%')
[('a', '0', '$'), ('m', '1', '#'), ('s', '2', '@')]