Tuples

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)
<class 'str'>

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

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

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

>>> t = tuple()
>>> type(t)
<class '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)
>>> print(t1[0])
a
>>> t is t1
True
>>> id(t) == id(t1)
True

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

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

Note

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)
(1,3)

>>> t={'one':'hana','two':'dool','three':'set'}
>>> t1=tuple(t)
>>> t1
('one', 'two', 'three')
>>> 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 0 positional arguments but 1 was 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)
>>> z
<zip object at 0x1027f5ec8>
>>> print(list(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(list(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=list(zip(e,k))
>>> eng2kor
[('one', 'hana'), ('two', 'dool'), ('three', 'set')]
>>> eng2kor=dict(eng2kor)
>>> eng2kor
{'one': 'hana', 'two': 'dool', 'three': 'set'}

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)
<class 'dict'>
>>> eng2kor.items()
dict_items([('one', 'hana'), ('two', 'dool'), ('three', 'set')])
>>> type(eng2kor.items())
<class 'dict_items'>

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

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