Skip to content

Commit

Permalink
Fixing Explanaitions, Examples and Typos
Browse files Browse the repository at this point in the history
  • Loading branch information
estebansolo committed Aug 1, 2020
1 parent 7e76025 commit 31f40fd
Show file tree
Hide file tree
Showing 19 changed files with 103 additions and 71 deletions.
14 changes: 8 additions & 6 deletions docs/01_args_and_kwargs.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Day 01 - *args and **kwargs

When we define functions, we can make use of two kinds of arguments, ***positional arguments*** and ***named arguments or keyword arguments***.
When defining functions, we can use of two kinds of arguments, ***positional arguments*** and ***named arguments or keyword arguments***.

Keyword arguments are normally used to declare arguments with a default value, which are then used in case we don't pass it in when we make the call.
`Keyword arguments` are normally used to declare arguments with a default value, which are then used in case we don't pass it in when we make the call.

## Positional Arguments

## Arguments
```python
def multiply(a, b):
print(a * b)
Expand Down Expand Up @@ -53,7 +54,7 @@ fun(1, 2, 3)
# Output: (1, 2, 3)
```

When we use *args we are treating all positional arguments as a **tuple**.
When using *args, all positional arguments are treated as a **tuple**.

## Use of **kwargs

Expand All @@ -75,7 +76,7 @@ fun(a=1, b=2, c=3)
# Output: {"a": 1,"b": 2,"c": 3}
```

When we use double asterisk (**) we are treating all keyword arguments as a **dict**.
When we use double asterisk (**), the keyword arguments are treated as a **dict**.

This functionality allows us to pass an indefinite list of arguments, either positional or named, and treat them as 1 or 2 variables in the function, this is because just as we can combine both types of arguments when defining a function, we can make use of both variables in the same function.

Expand Down Expand Up @@ -132,7 +133,7 @@ In this case we could use the double asterisk although the function has no argum

## Python Example

If we see the Python documentation, the [print](https://docs.python.org/3/library/functions.html#print) function makes use of *args, in its case and as I indicated at the beginning, it is not necessary that it is called this way.
If you see the Python documentation, the [print](https://docs.python.org/3/library/functions.html#print) function makes use of *args, in its case and as I indicated at the beginning, it is not necessary that it is called this way.

`print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)`

Expand All @@ -150,4 +151,5 @@ print(*values)
```

[Go to the Challenge](https://github.com/estebansolo/Python30/blob/master/exercises/01_args_and_kwargs.py)

[Go to the Solution](https://github.com/estebansolo/Python30/blob/master/solutions/01_args_and_kwargs.py)
24 changes: 10 additions & 14 deletions docs/02_range.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ So, In this case the sequence will start at 0 and end at 5 (not including it).
print(range(5))
```

We'll see that when printing it returns something similar to **range(0, 5)**, but what we want is to see the complete sequence, so to see the values that compose it, for this we must cast this range as a list
We'll see that when printing it returns something similar to **range(0, 5)**, but what we want is to see the complete sequence, so to see the values that compose it, for this we must cast this range as a list.

```python
sequence = list(range(5))
print(sequence)
```

The output is now more understandable
The output is now more understandable:

```
[0, 1, 2, 3, 4]
```

### Two parameters

When we call **range** passing two arguments, with the first value we define where the sequence starts and with the second one where it ends.
When we call **range** passing two parameters, with the first value we define where the sequence starts and with the second one where it ends.

**Remember that the value where it ends is not included in the sequence**

Expand All @@ -54,7 +54,7 @@ print(list(range(2, 9)))

### Three parameters

When we use the function with all its arguments, we will define where it starts, where it ends and how many steps the sequence will be.
Finally, when calling the function with all its arguments, we will define where it starts, where it ends, and how many steps the sequence will be.

```python
print(list(range(-5, 5, 2)))
Expand All @@ -63,14 +63,9 @@ print(list(range(-5, 5, 2)))
# [-5, -3, -1, 1, 3]
```

We can see that the sequence starts at -5 and ends at 5, but why doesn't he print the 4?
You can see that the sequence starts at -5 and ends at 5, but where's number 4?

This is due to the steps we are indicating, which are 2, this way it will omit 1 value before returning the next

```
# Include [-5, -3, -1, 1, 3]
# Exclude [-4, -2, 0, 2, 4]
```
This is due to the steps we are indicating, which are 2, this way it will omit 1 value before returning the next number.

## Notes

Expand All @@ -79,13 +74,14 @@ This is due to the steps we are indicating, which are 2, this way it will omit 1

**Try this**

```
print(list(5, -5, -1))
```python
print(list(range(5, -5, -1)))
```

## How can I use float numbers with range?

The answer, You can't... if you need to create a sequence of numbers with floating values, you could take a look to [numpy.arange](https://numpy.org/doc/stable/reference/generated/numpy.arange.html)
The answer, you can't... if you need to create a sequence of numbers with floating values, you could take a look to [numpy.arange](https://numpy.org/doc/stable/reference/generated/numpy.arange.html)

[Go to the Challenge](https://github.com/estebansolo/Python30/blob/master/exercises/02_range.py)

[Go to the Solution](https://github.com/estebansolo/Python30/blob/master/solutions/02_range.py)
15 changes: 8 additions & 7 deletions docs/03_list_slices.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Before explaining how list slices work we must emphasize a couple of things.
my_list[start:stop:step]
```

- `start`: (required) The initial value in the slice
- `start`: (required) The initial value in the slice.
- `stop`: (required) End of the slice, without including its value.
- `step`: (optional) The size of steps in the sequence the default value is 1

Expand All @@ -29,14 +29,14 @@ If you haven't tried, what do you think is the output?

Going back to what I said before "start and stop are required", actually they are not, but as we are talking about slices, taking a part of the list, we must define the colon (:), this way we indicate that we are going to take from the first index (since before the colon no value was defined) to the last index (since no value was defined after the colon), this way we are generating a new list with this range that would be exactly the same.

Now how about we try to generate a list from the second index onwards? We don't need to define where it ends but where it begins
Now how about we try to generate a list from the second index onwards? We don't need to define where it ends but where it begins.

```python
my_list = ["H", "E", "L", "L", "O"]
print(my_list[2:])
```

Let's remember what the indices would be like
Let's remember what the indices would be like:

```
["H", "E", "L", "L", "O"]
Expand All @@ -45,7 +45,7 @@ Let's remember what the indices would be like

As we are generating a slice from position 2 onwards we will get a list like the following

```python
```
["L", "L", "O"]
```

Expand All @@ -58,15 +58,15 @@ my_list = ["H", "E", "L", "L", "O"]
print(my_list[:-1])
```

It will take from the beginning to the second last element in the list
It will take from the beginning to the second last element in the list:

```python
```
["H", "E", "L", "L"]
```

## Step

The step works in the same way as in the function range, its default value is 1 up but we can modify it if we want to go faster or in reverse
The step works in the same way as in the function range, its default value is 1, but we can modify it if we want to go faster or in reverse.

How do we create a new list but increase it from 2 items?

Expand Down Expand Up @@ -102,4 +102,5 @@ print(hello[::-1])
**You can use this slices not only with lists**

[Go to the Challenge](https://github.com/estebansolo/Python30/blob/master/exercises/03_list_slices.py)

[Go to the Solution](https://github.com/estebansolo/Python30/blob/master/solutions/03_list_slices.py)
13 changes: 7 additions & 6 deletions docs/04_map.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Day 04 - Map

Python comes with some higher order functions which can be very useful when working in a functional way.
Python comes with some [higher order functions](https://en.wikipedia.org/wiki/Higher-order_function) which can be very useful when working in a functional way.

In this first case we'll look at the **Map function**. The map function receives 2 arguments in the following order:
In this first case we'll look at the `map` function. The map function receives two arguments in the following order:

- A function
- At least a sequence (list, tuple, iterator, etc)

## How does it work?

Each of the elements of the sequence will be delivered to the function, this process is done 1 to 1 and what it will do depends on what we define in the function.
Each of the elements of the sequence will be delivered to the function, this process is done 1 by 1 and what it will do depends on what we define in the function.

At the end we will obtain an iterator which will contain each of the results of the calls to the function.
At the end we will obtain a new sequence which will contain each of the results of the calls to the function.

```python
def multiply(element):
Expand All @@ -21,7 +21,7 @@ numbers = [2, 4, 6, 8]
print(map(multiply, numbers))
```

In this example each number in the list will be given to the function and this number will be multiplied by 2, we return its result which at the end we will have a similar iterator as follows
In this example each number in the list will be given to the function and this number will be multiplied by 2, we return its result which at the end we will have a similar iterator as follows:

```
<map object at 0x7f98f2b52150>
Expand Down Expand Up @@ -93,7 +93,8 @@ print(list(map(user, names, ages, countries)))
# ]
```

The way the map function works depends on whether we need to perform the same action for each of the elements in a sequence
The way the map function works depends on whether we need to perform the same action for each of the elements in a sequence.

[Go to the Challenge](https://github.com/estebansolo/Python30/blob/master/exercises/04_map.py)

[Go to the Solution](https://github.com/estebansolo/Python30/blob/master/solutions/04_map.py)
11 changes: 6 additions & 5 deletions docs/05_filter.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Day 05 - Filter

Another higher order function is **filter**, the function filter allows as its name indicates to filter a sequence and return only the values that fulfill a condition.
Another higher order function is `filter`, the function filter allows as its name indicates to filter a sequence and return only the values that fulfill a condition.

Like the Map function, it receives 2 arguments which are
Like the Map function, it receives 2 arguments which are:

- A function
- A sequence that is going to be filtered
- A function.
- A sequence that is going to be filtered.

## How does it work?

Each of the elements in the sequence will be delivered to the function, if the function returns **True** the value that is delivered will be kept, otherwise it will be discarded
Each of the elements in the sequence will be delivered to the function, if the function returns **True** the value that is delivered will be kept, otherwise it will be discarded.

```python
def keep_hello(element):
Expand Down Expand Up @@ -56,4 +56,5 @@ print(list(filter(validate_age, users)))
```

[Go to the Challenge](https://github.com/estebansolo/Python30/blob/master/exercises/05_filter.py)

[Go to the Solution](https://github.com/estebansolo/Python30/blob/master/solutions/05_filter.py)
15 changes: 12 additions & 3 deletions docs/06_reduce.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ This is the last higher order function we'll see and like the previous ones it g
- It doesn't return a list, it returns a single value.
- Must be imported.

`from functools import reduce`

## How does it work?

Suppose we have the following list
Suppose we have the following list:

```python
[2, 6, 9, 1]
```

The function **reduces** takes 2 values and performs an action, the result of this continues as the first parameter in the next execution and the same action is performed.
The **reduce** function takes 2 values and performs an action, the result of this continues as the first parameter in the next execution and the same action is performed.

For this case we will add the values:

Expand Down Expand Up @@ -53,7 +55,13 @@ Finally
- `num_b`: 1
- Final returned value: 19

It is not the best way to do it however to perform a new test. Let's join the following list and return a string.
It's not the best way to do it, but it's a simple way to understand it.

Let's join the following list and return a string:

```python
["My", "name", "is", "Esteban"]
```

```python
from functools import reduce
Expand All @@ -70,4 +78,5 @@ print(reduce(join_string, words))
```

[Go to the Challenge](https://github.com/estebansolo/Python30/blob/master/exercises/06_reduce.py)

[Go to the Solution](https://github.com/estebansolo/Python30/blob/master/solutions/06_reduce.py)
13 changes: 7 additions & 6 deletions docs/08_comprehensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ new_list = [output for i in sequence if condition]

Almost all the comprehensions work in a similar way depending on the type of structure we need to obtain.

- `new_list`: The variable which will contain the list
- `output`: The output of every element in the list
- `i`: Value in the sequence
- `condition`: (optional) Comprehensions can have conditions to decide which value it will keep
- `new_list`: The variable which will contain the list.
- `output`: The output of every element in the list.
- `i`: Value in the sequence.
- `condition`: (optional) Comprehensions can have conditions to decide which value it will keep.

### Common Example

Expand All @@ -33,7 +33,7 @@ for number in range(1, 6):
print(totals)
```

We can perform this same action with the **map** function as we saw before, however this time we will use comprehension
We can perform this same action with the **map** function as we saw before, however this time we will use comprehension:

```python
totals = [number * 2 for number in range(1, 6)]
Expand Down Expand Up @@ -76,7 +76,7 @@ print(new_dict)
# {5: 25, 8: 64, 2: 4, 6: 36, 3: 9}
```

Comprehension
#### Comprehension

```python
numbers = [5, 8, 2, 6, 3]
Expand All @@ -90,4 +90,5 @@ print(new_dict)
In this example we can also use conditionals, the same way we can work with other types of data such as sets or generators.

[Go to the Challenge](https://github.com/estebansolo/Python30/blob/master/exercises/08_comprehensions.py)

[Go to the Solution](https://github.com/estebansolo/Python30/blob/master/solutions/08_comprehensions.py)
7 changes: 5 additions & 2 deletions docs/09_enumerate.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Enumerate is a built-in Python function to which we can provide an iterator and return each of its elements in a tuple with a counter.

The syntax is as follows:

```python
enumerate(sequence, start=0)
```
Expand Down Expand Up @@ -29,11 +31,11 @@ for counter, element in enumerate(languages):
# 2 Java
```

The optional start argument can be manipulated with the argument called **start**.
The optional start argument can be manipulated with the argument called `start`.

```python
languages = ["Go", "Python", "Java"]
for counter, element in enumerate(languages):
for counter, element in enumerate(languages, start=1):
print(counter, element)

# Output:
Expand All @@ -43,4 +45,5 @@ for counter, element in enumerate(languages):
```

[Go to the Challenge](https://github.com/estebansolo/Python30/blob/master/exercises/09_enumerate.py)

[Go to the Solution](https://github.com/estebansolo/Python30/blob/master/solutions/09_enumerate.py)
7 changes: 4 additions & 3 deletions docs/10_error_handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Python provides us with a very useful structure that allows us to handle the err

`try/except` allows us to capture errors and manipulate them without stopping the workflow.

The `try` block contains the code that could cause an error and we''re going to capture it in except.
The `try` block contains the code that could cause an error and we're going to capture it in `except`.

```python
try:
Expand All @@ -19,7 +19,7 @@ The code above is intended to capture any error generated within the try structu

Although in the previous code we were able to capture the error, it is not a good practice to do so since we have no knowledge of what is wrong.

If our code generates any exceptions of which we are not aware, it could affect us instead of helping us. Python is included with some [excepciones](https://docs.python.org/3/library/exceptions.html#bltin-exceptions), however each library we use can have its own exceptions as well as we can create them ourselves.
If our code generates any exceptions of which we are not aware, it could affect us instead of helping us. Python comes with some [exceptions](https://docs.python.org/3/library/exceptions.html#bltin-exceptions), however each library can have its own exceptions as well as we can create our own.

```python
int("Hello")
Expand Down Expand Up @@ -73,7 +73,7 @@ except ValueError as err:

## Else

Usually when we hear about the `else` clause we relate it to conditionals, however in python we can use it for different structures, one of them is the **try/except**.
Usually when we hear about the `else` clause we relate it to conditionals, however in python we can use it for different structures, one of them is this.

The `else` clause allows us to execute the code if no exception has been generated.

Expand Down Expand Up @@ -111,4 +111,5 @@ finally:
```

[Go to the Challenge](https://github.com/estebansolo/Python30/blob/master/exercises/10_error_handling.py)

[Go to the Solution](https://github.com/estebansolo/Python30/blob/master/solutions/10_error_handling.py)

0 comments on commit 31f40fd

Please sign in to comment.