adds libraries
This commit is contained in:
parent
7347594700
commit
81fb6551e0
|
@ -85,12 +85,16 @@ print("Hello World!")
|
||||||
```
|
```
|
||||||
|
|
||||||
Just for reference below are a few helloworld programs in different languages.
|
Just for reference below are a few helloworld programs in different languages.
|
||||||
First `c#` then `c` and last but not least `javascript`.
|
First `c#` then `c` then `c++` and last but not least `javascript`.
|
||||||
|
|
||||||
|
### c#
|
||||||
|
|
||||||
```c#
|
```c#
|
||||||
Console.WriteLine("Hello World!");
|
Console.WriteLine("Hello World!");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### c
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@ -100,6 +104,21 @@ int main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### c++
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// Your First C++ Program
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "Hello World!";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### javascript
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
alert( 'Hello, world!' );
|
alert( 'Hello, world!' );
|
||||||
```
|
```
|
||||||
|
@ -375,6 +394,8 @@ True
|
||||||
|
|
||||||
Your first challenge!
|
Your first challenge!
|
||||||
I would like you to write a program that converts Celsius to Fahrenheit.
|
I would like you to write a program that converts Celsius to Fahrenheit.
|
||||||
|
You should do this in a **new** python file.
|
||||||
|
I suggest you call it `c_to_f.py` or something that makes sense to you.
|
||||||
The result of this program *could* be as follows.
|
The result of this program *could* be as follows.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -683,6 +704,8 @@ Think of some calculations such as the Celsius to Fahrenheit converter and creat
|
||||||
# Coding challenge - Pretty Print
|
# Coding challenge - Pretty Print
|
||||||
|
|
||||||
Can you write me a function that decorates a name or message with a *pretty* character.
|
Can you write me a function that decorates a name or message with a *pretty* character.
|
||||||
|
You should do this in a **new** python file.
|
||||||
|
I suggest you call it `pretty_frame.py` or something that makes sense to you.
|
||||||
Kind of like the two examples below.
|
Kind of like the two examples below.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -776,6 +799,8 @@ Also think about how you can *break* this program!
|
||||||
That being said, we all die and we all live in a country with a life expectancy.
|
That being said, we all die and we all live in a country with a life expectancy.
|
||||||
The [Belgian](https://www.healthybelgium.be/en/health-status/life-expectancy-and-quality-of-life/life-expectancy) life expectancy for a man is about 80 years so if you know your birthday, which you should, you can calculate your theoretical death day.
|
The [Belgian](https://www.healthybelgium.be/en/health-status/life-expectancy-and-quality-of-life/life-expectancy) life expectancy for a man is about 80 years so if you know your birthday, which you should, you can calculate your theoretical death day.
|
||||||
Plus, you can calculate the percentage of your life that remains.
|
Plus, you can calculate the percentage of your life that remains.
|
||||||
|
You should do this in a **new** python file.
|
||||||
|
I suggest you call it `memento_mori.py` or something that makes sense to you.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Spoiler warning</summary>
|
<summary>Spoiler warning</summary>
|
||||||
|
@ -797,7 +822,7 @@ days_to_live = memento_mori - datetime.datetime.now().date()
|
||||||
percentage = (days_to_live.days / life_expectancy_days) * 100
|
percentage = (days_to_live.days / life_expectancy_days) * 100
|
||||||
|
|
||||||
print("your theoretical death day is:", memento_mori)
|
print("your theoretical death day is:", memento_mori)
|
||||||
print("that's", days_to_live.days, "left to live")
|
print("that's", days_to_live.days, "days left to live")
|
||||||
print("which means you have {:.2f}% left to live...".format(percentage))
|
print("which means you have {:.2f}% left to live...".format(percentage))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -808,17 +833,242 @@ Take your time to ask me about them, or use online documentation and keep some n
|
||||||
|
|
||||||
# Writing your first library
|
# Writing your first library
|
||||||
|
|
||||||
TODO import pretty print and digital dice
|
Up until now have coded our own functions and usage of these functions.
|
||||||
|
We've seen there is no need to always write everything from scratch as we can *reuse* existing code by importing libraries and calling it's functions.
|
||||||
|
But what are those libraries actually?
|
||||||
|
|
||||||
## What are libraries?
|
Consider the following mini script.
|
||||||
|
It imports `datetime` and calls the `now` function to print the date and time.
|
||||||
|
A pretty basic clock.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
timestamp = datetime.datetime.now()
|
||||||
|
print("It is: {}".format(timestamp))
|
||||||
|
```
|
||||||
|
|
||||||
|
When you put your cursor on the `now` part of the function call, you can press **CTRL-b** to go to the **declaration** of said function.
|
||||||
|
You can also right click on the `now` part and see all possible *actions* you can perform on this function.
|
||||||
|
This opens up a **second tab** in your editor window with a `datetime.py` file in it.
|
||||||
|
In this file your cursor should have jumped to the following code.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
@classmethod
|
||||||
|
def now(cls, tz=None):
|
||||||
|
"Construct a datetime from time.time() and optional time zone info."
|
||||||
|
t = _time.time()
|
||||||
|
return cls.fromtimestamp(t, tz)
|
||||||
|
```
|
||||||
|
|
||||||
|
What does this look like?
|
||||||
|
It looks like python code no?
|
||||||
|
Well, it is!
|
||||||
|
Libraries are often *just* other python files we load into our program.
|
||||||
|
So if they are just python files we *should* be able to write our own libraries no?
|
||||||
|
|
||||||
|
🏃 Try it
|
||||||
|
---
|
||||||
|
|
||||||
|
Import some libraries and go peak at some function declarations.
|
||||||
|
A big part of code writing is *navigating* a codebase written by other people.
|
||||||
|
Properly understanding how to navigate is essential!
|
||||||
|
|
||||||
## How do we write libraries?
|
## How do we write libraries?
|
||||||
|
|
||||||
|
Let's go back to our `pretty_print` function.
|
||||||
|
I have code along these lines.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
def pretty_print(msg, decorator="#"):
|
||||||
|
line_len = len(msg) + (len(decorator) * 2) + 2
|
||||||
|
print(decorator * line_len)
|
||||||
|
print("{} {} {}".format(decorator, msg, decorator))
|
||||||
|
print(decorator * line_len)
|
||||||
|
|
||||||
|
pretty_print("Wouter")
|
||||||
|
pretty_print("Python rules!")
|
||||||
|
pretty_print("Alice", "-")
|
||||||
|
```
|
||||||
|
|
||||||
|
I'll **create a new python file** and name it `helper_functions.py`.
|
||||||
|
In this file I rewrite (don't copy paste, you need the practice) my function.
|
||||||
|
As I'm rewriting my function I'll also need some test calls to my function.
|
||||||
|
Done!
|
||||||
|
|
||||||
|
Now in a **second new python file** I'll name `my_program.py` I'll `import` the `helper_fucntions.py` file.
|
||||||
|
Note the syntax drops the `.py` extension!
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import helper_functions
|
||||||
|
|
||||||
|
|
||||||
|
print("I'm a program")
|
||||||
|
helper_functions.pretty_print("hello world!")
|
||||||
|
```
|
||||||
|
|
||||||
|
If we now **run** the `my_program.py` file we get the following output.
|
||||||
|
|
||||||
|
```
|
||||||
|
##########
|
||||||
|
# Wouter #
|
||||||
|
##########
|
||||||
|
#################
|
||||||
|
# Python rules! #
|
||||||
|
#################
|
||||||
|
---------
|
||||||
|
- Alice -
|
||||||
|
---------
|
||||||
|
I'm a program
|
||||||
|
################
|
||||||
|
# hello world! #
|
||||||
|
################
|
||||||
|
```
|
||||||
|
|
||||||
|
OK, it *kind* of works, the function get's called from within the `my_program.py` file but the test calls from the `helper_functions.py` file are messing up my execution.
|
||||||
|
Luckily there is a way to tell python to only run certain code when a file should be seen as program and not a library.
|
||||||
|
Sounds complicated but it's logically very simple.
|
||||||
|
|
||||||
## What is `__name__ == "__main__"`?
|
## What is `__name__ == "__main__"`?
|
||||||
|
|
||||||
|
Remember on the first day when I showed you how python is self documenting via `print.__doc__`?
|
||||||
|
Well, there are [more](https://stackoverflow.com/questions/20340815/built-in-magic-variable-names-attributes) *magical attributes* than just the `__doc__` one!
|
||||||
|
There is one called `__name__` which is used for the exact purpose we're trying to achieve.
|
||||||
|
Go back to the `helper_functions.py` file and comment out the test calls and add the line that print's the `__name__` variable.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
def pretty_print(msg, decorator="#"):
|
||||||
|
line_len = len(msg) + (len(decorator) * 2) + 2
|
||||||
|
print(decorator * line_len)
|
||||||
|
print("{} {} {}".format(decorator, msg, decorator))
|
||||||
|
print(decorator * line_len)
|
||||||
|
|
||||||
|
|
||||||
|
print("I'm a library")
|
||||||
|
print("my name is: {}".format(__name__))
|
||||||
|
# pretty_print("Wouter")
|
||||||
|
# pretty_print("Python rules!")
|
||||||
|
# pretty_print("Alice", "-")
|
||||||
|
```
|
||||||
|
|
||||||
|
Do the same in the `my_program.py` file so it look similar to the code below.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import helper_functions
|
||||||
|
|
||||||
|
|
||||||
|
print("I'm a program")
|
||||||
|
print("my name is: {}".format(__name__))
|
||||||
|
helper_functions.pretty_print("hello world!")
|
||||||
|
```
|
||||||
|
|
||||||
|
If you now run the `helper_functions.py` file you should get output similar to this.
|
||||||
|
|
||||||
|
```
|
||||||
|
I'm a library
|
||||||
|
my name is: __main__
|
||||||
|
```
|
||||||
|
|
||||||
|
But when you run the `my_program.py` you should get something like this.
|
||||||
|
|
||||||
|
```
|
||||||
|
I'm a library
|
||||||
|
my name is: helper_functions
|
||||||
|
I'm a program
|
||||||
|
my name is: __main__
|
||||||
|
################
|
||||||
|
# hello world! #
|
||||||
|
################
|
||||||
|
```
|
||||||
|
|
||||||
|
This shows that the `__name__` variable changes according to how a script is called and this behavior can be used to our advantage!
|
||||||
|
We can *evaluate* the value behind `__name__` and change execution accordingly.
|
||||||
|
Evaluating and changing execution screams **conditional logic** no?
|
||||||
|
So in the library we add the following.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
def pretty_print(msg, decorator="#"):
|
||||||
|
line_len = len(msg) + (len(decorator) * 2) + 2
|
||||||
|
print(decorator * line_len)
|
||||||
|
print("{} {} {}".format(decorator, msg, decorator))
|
||||||
|
print(decorator * line_len)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
pretty_print("Wouter")
|
||||||
|
pretty_print("Python rules!")
|
||||||
|
pretty_print("Alice", "-")
|
||||||
|
```
|
||||||
|
|
||||||
|
Only when the library is executed as a program, for example when we're testing out out functions, the condition is met to allow execution of our calls.
|
||||||
|
Problem sorted!
|
||||||
|
Executing our main program now gives the expected output.
|
||||||
|
|
||||||
|
```
|
||||||
|
I'm a program
|
||||||
|
my name is: __main__
|
||||||
|
################
|
||||||
|
# hello world! #
|
||||||
|
################
|
||||||
|
```
|
||||||
|
|
||||||
## Anatomy of a program
|
## Anatomy of a program
|
||||||
|
|
||||||
TODO imports, functions, execution
|
While it's still very early in your coding career I *really* want to insist on good practices from the start as it will help you make sense of it all.
|
||||||
|
A well written script or program is divided into **three** sections.
|
||||||
|
|
||||||
|
1. We collect external tools from libraries, either from the standard library or of our own making.
|
||||||
|
2. We write the specific tools we need for our program to run.
|
||||||
|
3. We call a combination of **external** and **specific** tools which constitutes our program logic.
|
||||||
|
|
||||||
|
A mock-up program that follows these rules could look like this.
|
||||||
|
Notice how it's easy to read?
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import random
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def first_function():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def second_function():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def third_function():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def fourth_function():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("today it's: {}".format(datetime.datetime.now()))
|
||||||
|
choice = random.randint(0, 100)
|
||||||
|
if choice < 50:
|
||||||
|
first_function()
|
||||||
|
elif choice > 90:
|
||||||
|
second_function()
|
||||||
|
elif choice == 55:
|
||||||
|
third_function()
|
||||||
|
else:
|
||||||
|
fourth_function()
|
||||||
|
```
|
||||||
|
|
||||||
|
🏃 Try it
|
||||||
|
---
|
||||||
|
|
||||||
|
Go online and look for some scripts and programs that interest you.
|
||||||
|
See if you can assess whether the code follows the pattern I outlined.
|
||||||
|
There are a couple of things you should definitely read up on.
|
||||||
|
|
||||||
|
* The [zen](https://www.python.org/dev/peps/pep-0020/) of python.
|
||||||
|
* What is [pythonic](https://stackoverflow.com/questions/25011078/what-does-pythonic-mean)?
|
||||||
|
* Coding [style](https://docs.python-guide.org/writing/style/)
|
||||||
|
|
||||||
# While loop
|
# While loop
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue