# Introduction to Python Programming¶

This tutorial provides a basic overview of Python (>= 3.6) specifically for data analytics. In particular, we do not cover object-oriented programming (OOP) aspects of Python, how to manage errors and exceptions, etc. Python is a mature general-purpose programming language and has lots of bells and whistles accordingly. However, for introductory data analytics, you only need to be proficient in a certain subset of all the features that Python has to offer and our goal here is to focus on these features only. This tutorial does not assume any prior programming experience of any kind, though some background in functional programming would certainly be beneficial. The reader is referred to this book for a solid introduction to the Python programming language. If you would like a cheat sheet for Python basics, this one here is quite useful.

Let's first suppress warnings as they can get annoying sometimes.

In [ ]:

```
import warnings
warnings.filterwarnings('ignore')
```

In Python, comments are indicated with a "#" (pound) sign. Anything that comes after the # sign is ignored by the Python interpreter.
If you want to execute a line but suppress its output, you can end the line with a semi-colon.

In [ ]:

```
# we would like to run the line below,
# but we would like to hide its output:
2+2;
```

## Variables¶

In Python, you can assign a name to a value and this name is called a "variable". To create a variable, you use the

`=`

sign.
In [3]:

```
x = 'Hello' # here, x is of "string" base type, which we discuss further below
```

Once you define the variable x, you can use that variable instead of its actual value. Let's verify this using the

`print`

**function**(sometimes we will refer to a function as a "**command**" or "**method**" - practically they all mean the same thing).In [4]:

```
print(x)
```

Hello

You can assign the same value to more than one variable.

In [5]:

```
y = z = 23
print(y)
print(z)
```

23 23

Python allows you to assign multiple variables to multiple values simultaneously. This is called

**multiple assignment**.In [6]:

```
a, b, c = 3.14, 'Hello', 1887
print(a, b, c)
```

3.14 Hello 1887

In Python, you can easily swap values between multiple variables as below.

In [7]:

```
a, b, c = c, b, a
print(a, b, c)
```

1887 Hello 3.14

If you no longer need a variable, you can delete it from your computer's memory by using the

`del()`

function.
In [8]:

```
del(x)
```

## Base Data Types in Python¶

Python has the following base data types (there is also a`byte`

base type, but we do not cover this).
Type | Description |
---|---|

int | Integer |

float | Floating-point number |

str | String |

bool | Boolean (True or False) |

To see the type of an object, you can use the

`type()`

function.
In [9]:

```
type(10)
```

Out[9]:

int

In [10]:

```
type(10.5)
```

Out[10]:

float

In [11]:

```
type('Python')
```

Out[11]:

str

In [12]:

```
type(True)
```

Out[12]:

bool

### Integers¶

In Python, you can construct integer values with no limits on the number of digits. Below, ** is the power operator.

In [13]:

```
long_integer = 12**34
print(long_integer)
```

4922235242952026704037113243122008064

The function

`int()`

lets you construct an integer number from a (compatible) string.
In [14]:

```
x = int('10')
print(x)
```

10

In [15]:

```
type(x)
```

Out[15]:

int

While converting from

`string`

to `integer`

, you will get an error if the string you are trying to convert does not represent any numbers.
In [16]:

```
# this will not work: x = int('Python')
```

### Floats¶

Real numbers are represented by floating-points in Python.

In [17]:

```
f = 18.87
print(f)
```

18.87

If you use

`int()`

with a floating-point number, you will only get the integer part of that number.
In [18]:

```
f = int(18.87)
print(f)
```

18

In [19]:

```
type(f)
```

Out[19]:

int

We can use the

`float()`

function to define a floating-point number from a (compatible) string.
In [20]:

```
f = float('18.87')
print(f)
```

18.87

In [21]:

```
type(f)
```

Out[21]:

float

### Strings¶

A

*string*is a sequence of characters. In Python, strings are enclosed in either single or double quotes - it doesn't matter which one you use. However, we recommend using**single quotes**over double quotes since you can create them with one less key press!In [22]:

```
s1 = "I love chocolate."
s2 = 'I love chocolate.'
print(s1)
print(s2)
```

I love chocolate. I love chocolate.

The exception here is that if you need to put a single quote in your string, you need to put the entire string inside double quotes and vice versa.

In [23]:

```
s3 = "Let's learn some Python."
s4 = 'The most popular languages for data analysis are apparently "R" and "Python".'
print(s3)
print(s4)
```

The

`str()`

function constructs a string from other compatible data types.
In [24]:

```
s5 = str('Python')
print(s5)
```

Python

In [25]:

```
type(s5)
```

Out[25]:

str

In [26]:

```
s6 = str(18.87)
print(s6)
```

18.87

In [27]:

```
type(s6)
```

Out[27]:

str

Starting Python

*3.6*, you can use`f-strings`

to put other variables inside strings. This is extremely handy.
In [28]:

```
name = 'pi'
value = 3.14
print(f'The value of {name} is {value}.')
```

The value of pi is 3.14.

The function

`find()`

returns the starting index of a given sequence of characters in the string. If not found, it returns -1.
In [29]:

```
print(s1.find('I'))
print(s1.find('we'))
```

0 -1

`startswith()`

checks if a string starts with a particular sequence of characters.
In [30]:

```
print(s1.startswith('I love'))
```

True

`endswith()`

checks if a string ends with a particular sequence of characters.
In [31]:

```
print(s1.endswith('.'))
```

True

`count()`

counts the number of occurance of a sequence of characters in the given string.
In [32]:

```
print(s1.count('e'))
print(s1.count('ee'))
```

2 0

`lower()`

converts any upper case to lower and `upper()`

does vice versa.
In [33]:

```
print(s1)
print(s1.lower())
print(s1.upper())
```

I love chocolate. i love chocolate. I LOVE CHOCOLATE.

The function

`replace()`

replaces one substring with another one. You need to pay attention that Python strings are **immutable**, that is, you cannot change a string once it is defined. However, you can replace a substring and set the output to a new string (possibly the original string), as shown below.In [34]:

```
s1.replace('I','We all')
# Python strings are immutable!
# You cannot change them in place
print(s1)
# But the following will change the string s1
s1= s1.replace('I','We all')
print(s1)
```

I love chocolate. We all love chocolate.

For other methods that are available for a string (or any other data structure), you can use the

**tab completion feature**of Jupyter Notebook. Just define a string, put a dot, and then hit the`tab`

button.
In [35]:

```
st = 'aBc'
st.swapcase()
```

Out[35]:

'AbC'

A string is actually of a

**container type**, so you can combine two strings using the "+" sign.In [36]:

```
first_string = 'I love '
second_string = 'chocolate.'
print(first_string + second_string)
```

I love chocolate.

### Booleans¶

Boolean represents logical values: True or False. The function or .

`bool()`

returns either `True`

or `False`

based on its input parameter. In particular, `bool()`

will always return `True`

unless its input parameter is one of the below:
- Empty (such as
`[]`

(empty list),`()`

(empty tuple),`{}`

(empty dictionary)) - False
- None (this is a Python keyword for undefined objects)
- 0

**NOTE:**Python is a*case sensitive*programming language. Therefore, valid boolean values are`True`

and `False`

, not `true`

`false`

In [37]:

```
bool(100)
```

Out[37]:

True

In [38]:

```
bool(True)
```

Out[38]:

True

In [39]:

```
bool([])
```

Out[39]:

False

In [40]:

```
bool(False)
```

Out[40]:

False

In [41]:

```
bool(None)
```

Out[41]:

False

In [42]:

```
bool(0)
```

Out[42]:

False

## Comparison and Logical Operators¶

In Python, comparison and logical operators allows you to evaluate a condition to a single

*boolean*value,`True`

or `False`

.
### Comparison Operators¶

Operator | Meaning |
---|---|

== |
True, if equal |

!= |
True, if not equal to |

< |
less than |

> |
greater than |

<= |
less than or equal to |

>= |
greater than or equal to |

In [43]:

```
x = 1000
y = 2000
```

In [44]:

```
print('x == y:', x == y)
print('x != y:', x != y)
print('x < y:', x < y)
print('x > y:', x > y)
print('x <= y:', x <= y)
print('x >= y:', x >= y)
```

x == y: False x != y: True x < y: True x > y: False x <= y: True x >= y: False

You can also compare

*strings*with comparison operators.In [45]:

```
string_1 = 'Python'
string_2 = 'PYTHON'
```

In [46]:

```
print(string_1 + ' == ' + string_2 + ':', string_1 == string_2)
```

Python == PYTHON: False

Alternatively, for base types, instead

`==`

or `!=`

, you can use `is`

or `is not`

respectively.
In [47]:

```
print('x is y:', x is y)
print('x is not y:', x is not y)
```

x is y: False x is not y: True

### Logical Operators¶

You can use logical operators to compare boolean values.Operator | Meaning |
---|---|

and |
True, if both statements are true |

or |
True, if one of statements is true |

not |
False, if the result is true |

In [48]:

```
(18 == 18) and (18 != -1)
```

Out[48]:

True

In [49]:

```
(10 < 15) or (19 > 20)
```

Out[49]:

True

In [50]:

```
not(1900 >= 2000)
```

Out[50]:

True

## Basic Mathematical Operations¶

Operator | Task Performed |
---|---|

+ | Addition |

- | Subtraction |

/ | Division |

// | Floor division |

* | Multiplication |

% | Modulo |

** | Exponent |

In [51]:

```
2 + 3
```

Out[51]:

5

In [52]:

```
20 - 13
```

Out[52]:

7

In [53]:

```
4/2
```

Out[53]:

2.0

The

`/`

operator always results in a float, even if the result is actually an integer.
In [54]:

```
print(type(4/2))
```

<class 'float'>

In [55]:

```
4/3
```

Out[55]:

1.3333333333333333

The operator

`//`

results in an integer division such that only the integer part is kept and the result is of integer type.
In [56]:

```
4//3
```

Out[56]:

1

In [57]:

```
print(type(4//3))
```

<class 'int'>

In [58]:

```
23*10
```

Out[58]:

230

In [59]:

```
23%10
```

Out[59]:

3

In [60]:

```
2**10
```

Out[60]:

1024

You can also use the

`pow()`

function to compute "x to the power y".
In [61]:

```
pow(2, 10)
```

Out[61]:

1024

`round()`

simply rounds a number based on the specified number of decimals.
In [62]:

```
round(3.14159265359, 0)
```

Out[62]:

3.0

In [63]:

```
round(3.14159265359, 1)
```

Out[63]:

3.1

In [64]:

```
round(3.14159265359, 2)
```

Out[64]:

3.14

Expect to see some strange behavior with

`round()`

- for instance, rounding to an integer is done to the nearest even number! Unlike what you might expect, rounding is a very tricky business and it has even caused fatalities. For a detailed explanation for rounding in Python, please see this.
In [65]:

```
round(3.5, 0)
```

Out[65]:

4.0

In [66]:

```
round(4.5, 0)
```

Out[66]:

4.0

`abs()`

returns the absolute value of its input parameter.
In [67]:

```
abs(-3.4)
```

Out[67]:

3.4

## Containers¶

Python defines two types of containers:- Ordered sequences (lists, tuples, and strings)
- Key containers (dictionaries and sets).

### Lists¶

A Python

*list*is an ordered sequence of elements that is enclosed in square brackets and separated by a comma. You can access any of these elements by simply referring to its index value. You can put any combination of data types into a list. Lists are declared by`[]`

or `list()`

.
In [68]:

```
# create an empty list
list0 = []
list1 = list()
print(type(list0), type(list1))
```

<class 'list'> <class 'list'>

In [69]:

```
lst = [1, 1.23, True, 'hello', None]
print(lst)
```

[1, 1.23, True, 'hello', None]

In [70]:

```
lst = list((1, 1.23, True, 'hello', None)) # notice the double round brackets
print(lst)
```

[1, 1.23, True, 'hello', None]

In [71]:

```
cars = ['Toyota', 'Mercedes', 'Ford']
```

In [72]:

```
print(cars)
```

['Toyota', 'Mercedes', 'Ford']

**NOTE:**In Python, indexing starts from 0. Thus, for instance, the list

`cars`

will have *Toyota*at 0 index,

*Mercedes*at 1 index, and

*Ford*at 2 index.

In [73]:

```
cars[0]
```

Out[73]:

'Toyota'

Indexing in reverse order is also possible. For instance, if you want to access Ford, the last element in

`cars`

, the index would be -1. And index -2 will be Mercedes, and finally index -3 will be Toyota.
In [74]:

```
cars[-1]
```

Out[74]:

'Ford'

Indexing is limited to accessing a single element. Slicing, on the other hand, is accessing a sequence of elements inside the list.

In [75]:

```
# pay attention to the range() function
# and how we use list() to convert the output to a proper list
num = list(range(0,10))
print(num)
```

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [76]:

```
print(num[0:4])
print(num[4:])
```

[0, 1, 2, 3] [4, 5, 6, 7, 8, 9]

In [77]:

```
print(num[-3:]) # get the 3 elements from the end
```

[7, 8, 9]

It is also possible to slice a parent list with a step length.

In [78]:

```
num[0:9:3]
```

Out[78]:

[0, 3, 6]

In [79]:

```
num[0:9:5]
```

Out[79]:

[0, 5]

As in lists, you can also access any character in a string through indexing and slicing.

In [80]:

```
name = 'Python'
print(name[0])
print(name[1:])
```

P ython

However, you cannot modify a string as strings are immutable.

In [81]:

```
# This will not work: name[3] = 'y'
```

#### Equal vs. Identical Lists¶

Pay attention to*equal*vs.

*identical*for two lists (or variables of other container types in general). The equality operator "==" checks whether two variables have the same contents. The "is" operator checks whether two variables are identical, that is, if they point to the same address in the memory. As the example below shows, two variables might have the same content, but they might be pointing to different addresses in the memory. (This distinction is only for container types; for base types (such as integers and strings), there is no difference between being equal and identical.)

In [82]:

```
x = y = [1, 2, 3] # both x and y point to the same address in the memory, so they are identical
z = [1, 2, 3] # z has the same content as x and y, but it points to a different address
print('x == y:', x == y)
print('z == y:', z == y)
print('x is y:', x is y)
# this is False as x and z point to different addresses
# in the memory even though they have the same contents
print('z is y:', z is y)
```

x == y: True z == y: True x is y: True z is y: False

#### Operations on Lists¶

`append()`

adds a element to the end of the list.
In [83]:

```
lst = [1, 2, 3, 4, 5]
print(lst)
lst.append(6)
print(lst)
```

[1, 2, 3, 4, 5] [1, 2, 3, 4, 5, 6]

`extend()`

adds another list at the end.
In [84]:

```
lst.extend([7, 8])
print(lst)
```

[1, 2, 3, 4, 5, 6, 7, 8]

Alternatively, you can use

`+`

to combine multiple lists (or multiple strings).
In [85]:

```
lst = lst + [9, 10]
print(lst)
```

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

If you want to insert an item at the position you specify, use

`insert(x, y)`

. Remember, `append()`

can insert the element only at the end.
In [86]:

```
lst.insert(5, 'Python')
print(lst)
```

[1, 2, 3, 4, 5, 'Python', 6, 7, 8, 9, 10]

You can use

`remove()`

to remove the first occurance of an element by specifying the element itself using the function.
In [87]:

```
lst.remove('Python')
print(lst)
```

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

`sort()`

method arranges the elements in ascending order **in place**. That is, the original list is updated with the new order. You can sort all numerical or all string lists, but not a mix of them.

In [88]:

```
lst_num = [3, 5, 1.23]
lst_num.sort()
print(lst_num)
```

[1.23, 3, 5]

In [89]:

```
lst_str = ['hello', 'world']
print(lst_str)
lst_str.sort(reverse=True)
print(lst_str)
```

['hello', 'world'] ['world', 'hello']

In [90]:

```
lst_mix = [3, 5, 1.23, 'hello']
# this will not work: lst_mix.sort()
```

For reversing a list in place, use

`reverse()`

In [91]:

```
lst_mix.reverse()
print(lst_mix)
```

['hello', 1.23, 5, 3]

If you do not want to modify the original list, use

`sorted()`

and `reversed()`

and set them equal to a new list.
In [92]:

```
lst = [3, 5, 1]
lst_new = sorted(lst)
print('original:', lst)
print('sorted:', lst_new)
lst_reversed = reversed(lst) # this returns an interator, not a list!
print('just reversed:', lst_reversed)
lst_reversed_list = list(lst_reversed)
print('reversed and re-listed:', lst_reversed_list)
```

`count()`

counts the number of a particular element that is present in the list. If there is none, it will return 0.
In [93]:

```
lst.count(1)
```

Out[93]:

1

`index()`

finds the index of a particular element. Note that if there are multiple elements of the same value then this will return the first index. if there is none, it will throw an error.
In [94]:

```
lst
```

Out[94]:

[3, 5, 1]

In [95]:

```
lst.index(1)
```

Out[95]:

2

For other methods that are available for a list (or any other object), you can use the

**tab completion feature**of Jupyter Notebook. Just define a list, put a dot, and then hit the`tab`

button.
In [96]:

```
lst.clear()
```

If you want your list to be immutable, that is unchangable, use the

**tuple**container. You can define a tuple by`()`

or `tuple()`

.
In [97]:

```
tpl = (1, 2, 3)
# You cannot change a tuple. For instance, try tpl[0] = 3.14
```

If you want a set in a mathematical sense, use the

**set**container. You can define a set by`set()`

. Python has a rich collection of methods for sets such as union, intersection, set difference, etc.
In [98]:

```
st = set([1, 1, 1, 2, 2, 2, 2])
print(st)
```

{1, 2}

### Dictionaries¶

Dictionaries are like a lookup table. A dictionary consists of "key: value" pairs. To define a dictionary, you can use either

`{}`

or `dict()`

.
In [99]:

```
# create an empty dictionary
dict0 = {}
dict1 = dict()
print(type(dict0), type(dict1))
```

<class 'dict'> <class 'dict'>

In [100]:

```
dict0 = {}
dict0['One'] = 1
dict0['Two'] = 2
dict0['Three'] = 3
print(dict0)
```

{'One': 1, 'Two': 2, 'Three': 3}

An alternative way to define a dictionary is below.

In [101]:

```
dict1 = {'One': 1, 'Two': 2, 'Three': 3}
print(dict1)
```

{'One': 1, 'Two': 2, 'Three': 3}

You can access the value '3' via the key 'Three'.

In [102]:

```
print(dict0['Three'])
```

3

#### Operations on Dictionaries¶

`values()`

returns a list of values in a dictionary.
In [103]:

```
dict0.values()
```

Out[103]:

dict_values([1, 2, 3])

`keys()`

returns all the keys in a dictionary.
In [104]:

```
dict0.keys()
```

Out[104]:

dict_keys(['One', 'Two', 'Three'])

`items()`

returns the list with all dictionary keys with values.
In [105]:

```
dict0.items()
```

Out[105]:

dict_items([('One', 1), ('Two', 2), ('Three', 3)])

`update()`

inserts items to a dictionary.
In [106]:

```
dict1 = {'Four': 4}
dict0.update(dict1)
dict0
```

Out[106]:

{'One': 1, 'Two': 2, 'Three': 3, 'Four': 4}

`clear()`

clears the entire dictionary.
In [107]:

```
dict0.clear()
print(dict0)
```

{}

### Common Operations on Containers¶

In [108]:

```
num = list(range(10))
print(num)
```

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

To find the length of the list, that is, the number of elements in a list, use the

`len()`

method. For dictionaries, this method will return the total number of items.
In [109]:

```
len(num)
```

Out[109]:

10

In [110]:

```
len(dict0)
```

Out[110]:

0

If a list consists of all numeric or all string elements, then

`min()`

and `max()`

gives the minimum and maximum value in the list.
In [111]:

```
min(num)
```

Out[111]:

0

In [112]:

```
max(num)
```

Out[112]:

9

In [113]:

```
num2 = num + ['hello']
# this won't work because not all elements are numeric: min(num2)
# min() and max() also work with strings:
st = ['one','two', 'three']
max(st)
```

Out[113]:

'two'

How to check if a particular element is in a predefined list or dictionary:

In [114]:

```
names = ['Earth','Air','Fire']
```

In [115]:

```
'Tree' in names
```

Out[115]:

False

In [116]:

```
'Air' in names
```

Out[116]:

True

For a dictionary,

`in`

checks the keys, not values.
In [117]:

```
dict0 = {'One': 1, 'Two': 2, 'Three': 3}
```

In [118]:

```
'One' in dict0
```

Out[118]:

True

In [119]:

```
'Four' in dict0
```

Out[119]:

False

## Conditional Statements and Loops¶

### If¶

Statement block is executed only if a condition is true.

```
if logical_condition:
statement(s)
```

Make sure you put

*colon*`:`

at the end **and**indent the next line (preferably by 4 spaces, not a tab).In [120]:

```
a = 2000
b = 1999
if a > b:
print('a is greater than b')
```

a is greater than b

### If-else¶

```
if logical_condition:
statement(s)
else:
statement(s)
```

In [121]:

```
a = 2000
b = 1999
if a < b:
print('b is greater than a')
else:
print('a is greater than b')
```

a is greater than b

### If-elif¶

```
if logical_condition:
statement(s)
elif:
statement(s)
else:
statement(s)
```

In [122]:

```
a = 2000
b = 2000
if b > a:
print('b is greater than a')
elif a == b:
print('a and b are equal')
else:
print('a is greater than b')
```

a and b are equal

### Nested if¶

You can also write if statements inside a if statement.

In [123]:

```
a = 1999
b = 2000
if a > b:
print('a > b')
elif a < b:
print('a < b')
if a == 1999:
print('a = 1999')
else:
print('a is not equal to 1999')
else:
print('a = b')
```

a < b a = 1999

### While¶

```
while logical_condition:
statement(s)
```

In [124]:

```
i = 1
while i < 10:
print(i*2)
i = i + 1
print('Mission accomplished!')
```

2 4 6 8 10 12 14 16 18 Mission accomplished!

### For¶

For each item of a sequence, statements are executed.

```
for variable in sequence:
statement(s)
```

**NOTE:**Keep in mind that the

*colon*

`:`

at the end **and**indentation of the next line are

**mandatory**.

In [125]:

```
for i in range(10):
print(i)
```

0 1 2 3 4 5 6 7 8 9

In [126]:

```
for i in [1, 5, 10, 15]:
print(i*5)
```

5 25 50 75

In [127]:

```
dict0 = {'One': 1, 'Two': 2, 'Three': 3}
for key, value in dict0.items():
print(f'key is {key}, value is {value}.')
```

key is One, value is 1. key is Two, value is 2. key is Three, value is 3.

### Break¶

`break`

terminates the loop when a condition becomes true.
In [128]:

```
for i in range(10):
print(i)
if i >= 4:
break
```

0 1 2 3 4

### Continue¶

Unlike

`break`

, when a condition becomes a true, `continue`

lets you skip the rest of the code inside a loop for the current iteration only and continue on with the next iteration.
In [129]:

```
for i in range(10):
if i == 2:
print('Ignoring 2')
continue
else:
print(i)
```

0 1 Ignoring 2 3 4 5 6 7 8 9

### List Comprehension¶

You can create a list with a for-loop as below. This is called list comprehension and it is a very commonly used Python feature.

```
[do_something_with_x for x in sequence]
```

For example, say we would like create a list of numbers ranging from 0 to 9.

In [130]:

```
[z for z in range(10)]
```

Out[130]:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

How to convert the above numbers to strings and then combine them with a dash in between:

In [131]:

```
st_lst = [str(z) for z in range(10)]
print('-'.join(st_lst))
```

0-1-2-3-4-5-6-7-8-9

- List comprehension is very flexible as you can have an additional conditional statement.
[do_something_with_x for x in sequence if x some_condition]

For example, how to return a list of even numbers ranging from 0 to 10:

In [132]:

```
[z for z in range(11) if z % 2 == 0]
```

Out[132]:

[0, 2, 4, 6, 8, 10]

## Functions¶

You can define your own functions that perform a particular task. You can also pass in input parameters to your functions. You define a function using the keyword

`def`

followed by the function name and any input parameters you might have. If you like, you can define default values for your parameters. Functions can return a value using the `return()`

command. If there is no return statement, the function will implicitly return `None`

. A typical syntax for a function is as follows.
```
def function_name(parameter):
""" documentation """
statement(s)
return(value)
```

In [133]:

```
def test_function():
print('test')
```

In [134]:

```
test_function()
```

test

In [135]:

```
def iLove(food):
print('I love ' + food)
```

In [136]:

```
iLove('chocolate')
```

I love chocolate

Here is another version of the above function that uses a default value for its input parameter.

In [137]:

```
def iLove(food='junk food'):
print('I love ' + food)
iLove()
```

I love junk food

Another example of function that performs a mathematical operation based on the input value.

In [138]:

```
def five_times(x):
return(5 * x)
```

In [139]:

```
five_times(3)
```

Out[139]:

15

It is always a good practice to document your functions. You should write the documentation right after declaring the function. For example, suppose you would like to create a

`square`

function to return the squared value of its input parameter.
In [140]:

```
def square(x):
"""
Returns the square of the input.
"""
return x ** 2
```

In [141]:

```
square(4)
```

Out[141]:

16

To access "documentation" of a function, you use its

`__doc__`

method.
In [142]:

```
square.__doc__
```

Out[142]:

'\n Returns the square of the input.\n '

## Object Introspection¶

For help with variables and functions, add

`?`

at the beginning.
In [143]:

```
# the output will appear in a box at the bottom of your browser.
?print
```

In [144]:

```
?square
```

With functions, add

`??`

at the beginning to see the source code, if available.
In [145]:

```
??square
```

## Modules¶

A module is just a code library. It's a file containing a collection of functions (also known as methods/ commands) and variables (also known as attributes) that you can include in your code. If someone has already written a module that you need, you can just use it instead of reinventing the wheel! The most commonly used modules in Python for data analytics are the

`NumPy`

, `Pandas`

, `StatsModels`

, and `Scikit-Learn`

modules.
You can see a list of available variables and functions in a module using the `dir()`

command.
In [146]:

```
import numpy as np
dir(np)[100:110]
```

Out[146]:

['array', 'array2string', 'array_equal', 'array_equiv', 'array_repr', 'array_split', 'array_str', 'asanyarray', 'asarray', 'asarray_chkfinite']

As a simple illustration, let's create a matrix using

`NumPy`

.
In [147]:

```
data = np.arange(12)
data.reshape(3,4)
```

Out[147]:

array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])

## Exercises¶

- Return a list of numbers ranging between 0 to 50 that are divisible by 3 and 5.

- Suppose we have the following dictionary. Add a new course named 'Introduction to Analytics' with course code MATH2350 to this dictionary.

```
course_names = {'MATH2319': 'Machine learning', 'MATH1298': 'Categorical Data Analysis'}
```

- Given a value
`x`

, write a function that checks if`x`

is a number and returns its squared value if so. If not, the function should return None.

### Solutions¶

- List comprehension
- Dictionaries
- Conditional statements and functions

```
[z for z in range(51) if z%3 == 0 and z%5 == 0]
```

```
course_names['MATH2350'] = 'Introduction to Analytics'
```

```
def square(x):
"""
Return the square of x if number, None otherwise.
"""
if isinstance(x, (int, float)):
return x ** 2
else:
return None
```

www.featureranking.com