Python Beginner Concepts Tutorial

# Incremental Development

Incremental development is a programming tactic I use everyday. The goal is to avoid debugging large complex programs. Instead, I incrementally write code and then test it to ensure each new code works as expected.

Here's how it works...

### Example Scenario

Let's say someone gives you two points and you want to find the slope of a line that connects both points.

We'll program this in incremental development so I'll re-copy code over into new code boxes with each increment and explain my reasonings along the way.

#### My Steps for Development

1) Write pseudocode line by line on how logic works

2) Write code line by line in Python

3) Run program and validate code works with dummy data

4) Repeat steps 2-3 until your function works as anticipated

## Begin Incremental Development

### Write Pseudocode to Draft Logic

The code below has `#` - known as comments before each line to indicate it's Python code, but won't be executed when you run your program.

```# input: x and y coordinates for two points
# make coordinate points easy integers to evaluate function
# can pass input into a function called slope_of_line
# numerator = (y_point_two - y_point_one)
# denominator = (x_point_two - x_point_one)
# slope of line is numerator divided by denominator
# return slope of line value
```

### Write Code and Continually Validate Work

#### Assign variables as coordinate points

I assigned variables to a tuple in the format (x_point, y_point) - similar to typical math notation.

```point_one = (1, 1)
point_two = (2, 3)
# slope is 2
```

I know the slope of this line should evalute to 2.

#### Define function and arguments

Write a function that has two arguments for our two data points.

I'll return None in order to validate:

1) We've defined the function correctly

2) Naming of our arguments is OK

I'll change the body of the function later. The practice of writing code such as this that's useful for debugging is called scaffolding. It helps validate parts of my logic now but it is not part of the final product.

```point_one = (1, 1)
point_two = (2, 3)
# slope is 2

def slope_of_line(first_point, second_point):
return None
```

Upon evaluting this code block, we receive no errors and no output as expected.

#### Call function to validate it returns None

```point_one = (1, 1)
point_two = (2, 3)
# slope is 2

def slope_of_line(first_point, second_point):
return None

print(slope_of_line(point_one, point_two))
```
```None
```

Great! We returned and printed `None` as expected.

#### Pass coordinate points as arguments to the function and return coordinate points

```point_one = (1, 1)
point_two = (2, 3)
# slope is 2

def slope_of_line(point_one, point_two):
return point_one, point_two

print(slope_of_line(point_one, point_two))
```
```((1, 1), (2, 3))
```

Great! We returned and printed our coordinate points as a tuple of tuples.

#### Calculate numerator of slope function

I assigned variable to represent the index of the x and y coordinates for our coordinate points. We'll use these variables multiple times so it makes sense to assign variables rather than continually write `0` and `1` - which may be prone to error.

```point_one = (1, 1)
point_two = (2, 3)
# slope is 2

def slope_of_line(point_one, point_two):
x_index = 0
y_index = 1
numerator = point_two[y_index] - point_one[y_index]
return numerator

print(slope_of_line(point_one, point_two))
```
```2
```

Excellent! We returned and printed `2` as expected.

#### Calculate denominator of slope function

```point_one = (1, 1)
point_two = (2, 3)
# slope is 2

def slope_of_line(point_one, point_two):
x_index = 0
y_index = 1
numerator = point_two[y_index] - point_one[y_index]
denominator = point_two[x_index] - point_one[x_index]

return numerator, denominator

print(slope_of_line(point_one, point_two))
```
```(2, 1)
```

Nice! We returned and printed the correct numerator and denominator values as expected.

#### Finalize function logic and return slope

```point_one = (1, 1)
point_two = (2, 3)
# slope is 2

def slope_of_line(point_one, point_two):
"""
Calculate slope of a line given two points

Keyword arguments:
point_one -- tuple of two numeric values
point_two -- tuple of two numeric values
"""
x_index = 0
y_index = 1
numerator = point_two[y_index] - point_one[y_index]
denominator = point_two[x_index] - point_one[x_index]
slope = numerator / denominator

return slope

print(slope_of_line(point_one, point_two))
```
```2.0
```

Great! Our function works as expected since it returned `2` as the slope.

However, we should test this function with several points to further validate the slope is always calculated to be correct.

### Test Function with Various Point Combinations

```point_one = (1, 1)
point_two = (2, 3)
point_three = (5, 5)
```
```def slope_of_line(point_one, point_two):
"""
Calculate slope of a line given two points

Keyword arguments:
point_one -- tuple of two numeric values
point_two -- tuple of two numeric values
"""
x_index = 0
y_index = 1
numerator = point_two[y_index] - point_one[y_index]
denominator = point_two[x_index] - point_one[x_index]
slope = numerator / denominator

return slope
```
```print(slope_of_line(point_one, point_two))  # should return 2
```
```2.0
```
```print(slope_of_line(point_one, point_three)) # should return 1
```
```1.0
```
```print(slope_of_line(point_two, point_three)) # should return 2/3 or 0.67
```
```0.6666666666666666
```

Brilliant! All our slope calculations work out to what we anticipated.