# 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)
<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]
'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
('two', 'one')
>>> t1[1]
'one'
```

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
('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', '@')]
```