Author: James Bourbeau

In :
%load_ext watermark
%watermark -d -v

2016-12-29

CPython 3.5.2
IPython 5.0.0


# Survey of some built-in types in Python¶

Let's get a feel for some of the built-in types in python. Specifically, we'll discuss some of the most commonly used types, how to change the type of an object, and how some numeric operations behave between different types. If you would like to know the type of something, you can always use python's built-in type() function.

# Built-in types¶

## Numeric types¶

In python there are three basic numerical types: integers, floating-point, and complex numbers. These types are denoted by int, float, and complex, repsectively. Generally speaking, integers represent whole numbers ( ...,-2, -1, 0, 1, 2,...), floats represent decimal numbers, and complex are, well, complex numbers (where the real and imaginary parts are both floats). Information regarding the precision of floating-point can be found via

In :
import sys
sys.float_info

Out:
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)

Numbers without a decimal point produce integers, while number that include a decimal (or an exponent sign) produce floats.

In :
a = 2
type(a)

Out:
int
In :
b = 6.47
type(b)

Out:
float
In :
c = 9e8
type(c)

Out:
float

A complex number can be created by including a 'j' or 'J' in a number. The corresponding real and imaginary parts of the complex number can be accessed using real and imag attributes.

In :
z = 7 + 4.3j
type(z)

Out:
complex
In :
z.real

Out:
7.0
In :
z.imag

Out:
4.3

Note that the real and imaginary parts for the complex type are floating-point numbers--regardless of whether or not there is a decimal point.

There are other built-in numeric types such as fractions and decimal, but I find int, float, and complex to be the most commonly used.

## Boolean type¶

Booleans are actually a subtype of integers with values represent one of two constant values: True or False. More will be discussed about booleans later on when we discuss type casting.

In :
n = True
type(n)

Out:
bool
In :
p = False
type(p)

Out:
bool

## Sequence types¶

Some commonly used sequence types are the list, tuple, and string. Denoted by list, tuple, and str, respectively. These can be thought of as an ordered containers that can store several different items. It is important to note that the items that are stored in a list or tuple need not be of the same type.

Lists are can be constructed in several ways. However, using square brackets with list items seperated by commas is very common.

In :
d = [1, 2.3, 5, 74.7]
type(d)

Out:
list

Tuples can be construced similarly, but with parenthesis instead of square brackets.

In :
f = (83.2, -4 ,5e7)
type(f)

Out:
tuple

One weird quirk is that a tuple with a single item needs to have a trailing comma, e.g.

In :
f = (83.2,)
print(f)
type(f)

(83.2,)

Out:
tuple

If this trailing comma is left out, then python will assume you don't actually want a tuple and will assign whatever the single item is in parenthesis to your variable. For example,

In :
f = (83.2)
print(f)
type(f)

83.2

Out:
float

Each item in a sequence has a number to represent its location in the sequence. This number, called the index, starts at 0 for the first item, 1 for the second item, and so on. One can access an individual item in a sequence by using square brackets and the item's index. For example, the first item in the d list is

In :
d

Out:
1

The second item in the d list is

In :
d

Out:
2.3

The third item in the d list is

In :
d

Out:
5

and so on...

The length of a sequence, the number of items is contains, can be found with the built-in len() function.

In :
print(d)
len(d)

[1, 2.3, 5, 74.7]

Out:
4

Up to this point, it may seem like lists and tuples aren't any different. They are both containers that can hold items, you can access the items with an index, etc. How are these things different? The difference between the list type and the tuple type is that lists are mutable, while tuples are immutable. Mutable objects are objects that can be changed in place, while immutable objects cannot be changed in place. Let's look at an example.

Let's create a list

In :
g = [1, 2, 3, 4]
print(g)

[1, 2, 3, 4]


Now let's modify the list in place. That is, let's try to change the items in the list without creating a whole new list.

In :
g = 99
print(g)

[99, 2, 3, 4]


As you can see, there wasn't a problem here. We assigned to the variable g the list [1, 2, 3, 4], then modified the first item in the g list to be the number 99. This is an example of a mutable object—it can be changed. Let's try the same thing with a tuple now.

In :
g = (1, 2, 3, 4)
print(g)

(1, 2, 3, 4)

In :
g = 99
print(g)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-22-79deaff0a4bf> in <module>()
----> 1 g = 99
2 print(g)

TypeError: 'tuple' object does not support item assignment

We got this error because tuples are immutable—they can't be modified once they're created.

### String type¶

Strings are another sequence type and are used to represent a sequence of characters. Strings can be created by enclosing characters in either single or double quotes.

In :
g = 'pizza'
type(g)

Out:
str
In :
h = "jamesbond007"
type(h)

Out:
str

Because a string is a sequence, it can also be index just like lists and tuples.

In :
h

Out:
'j'
In :
h

Out:
'a'

You can also find out how many characters are in a string using the len() function

In :
len(h)

Out:
12

## Mapping types¶

In python, there is only one mapping type: the dictionary. It is denoted by dict. Dictionaries are unordered containers for key-value pairs. That is, for each key in a dictionary there is an associated value. Dictionaries are created by placing comma-separated key-value pairs inside curly brackets {}. For a key-value pair, the key and corresponding value are seperated by a colon, :.

An example might help...

In :
k = {'key1': 23, 'key2': -53.2, 'key3': 'Tokyo'}
type(k)

Out:
dict

Here, the dictionary keys are 'key1', 'key2', and 'key3', with corresponding values of 23, -53.2, and 'Tokyo'. In a similar way to sequences, you can access the values in a dicionary by giving the corresponding key in square brackets.

In :
k['key1']

Out:
23
In :
k['key2']

Out:
-53.2
In :
k['key3']

Out:
'Tokyo'

The size of a dictionary, the number of key-value pairs is contains, can be found with the built-in len() function.

In :
len(k)

Out:
3

It is important to note that in the previous example all the keys were strings, but this doesn't have to be the case. The only restriction on keys is that they be an immutable type. For example, the following is also an acceptable dictionary.

In :
m = {-23: [1, 2, 3, 4], 'desk': 3.2, 7.12: (-3, 'bird')}

In :
m[-23]

Out:
[1, 2, 3, 4]
In :
m['desk']

Out:
3.2
In :
m[7.12]

Out:
(-3, 'bird')

Let see what happens if I try to contruct a dictionary with a list key

In :
n = {[1, 2, 3]: 'WOO'}

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-37-484e2f71ab36> in <module>()
----> 1 n = {[1, 2, 3]: 'WOO'}

TypeError: unhashable type: 'list'

Whoops lists are mutable! So remember to always use immutable objects for dictionary keys!

# Type casting¶

Sometimes it can be useful to manually change the type of an object. In python, this so-called 'type-casting' can be accomplished using several built-in functions:

• int()—casts to integer
• float()—casts to float
• str()—casts to string
• bool()—casts to boolean

Let's see it in action

Casting integers to floats is fairly straight-forward

In :
a = float(2)
print(a)
type(a)

2.0

Out:
float

When casting a float to an integer, python will round down to the nearest integer

In :
b = int(78.81)
print(b)
type(b)

78

Out:
int

You can even cast a number to a string! (This effectively just returns the number in quotes)

In :
c = str(-1324.1)
print(c)
type(c)

-1324.1

Out:
str

Things get a little less straight-forward when casting to bool. Below are the bool casting rules:

• Numbers: Zero of any numeric type, for example, 0, 0.0, 0j, cast to False. Everything else casts to True.
• Sequences: Any empty sequence, for example, (), [], '', cast to False. Everything else casts to True.
• Mapping: The empty dictionary, {}, casts to False. Everything else casts to True.

Here are some examples:

In :
bool(0)

Out:
False
In :
bool(178.3)

Out:
True
In :
bool([])

Out:
False
In :
bool([1, 2, 3, 4, 5])

Out:
True
In :
bool({})

Out:
False
In :
bool({'key': 'value'})

Out:
True

# Numeric operations¶

The following numerical operations are supported for numeric types:

• Addition: +
• Subtraction: -
• Multiplication: *
• Division: /
• Floored division: //
• Exponentiation: **

Some examples...

In :
1+1

Out:
2
In :
10-3

Out:
7
In :
3*5.0

Out:
15.0
In :
5/2

Out:
2.5
In :
5//3

Out:
1
In :
9.0**2

Out:
81.0

When performing numeric operations, the type of numbers does matter. According to the Python Software Foundation:

Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the 'narrower' type is widened to that of the other, where integer is narrower than floating point, which is narrower than complex.

So, when you have a numeric operation with mixed numeric types, say adding an int and a float, the result will have the 'widest' type of the two numbers, in this case float. The convention is int is the most narrow type, float is wider than int, and complex is wider than float.