Merge branch 'master' of ssh://86thumbs.net:3022/waldek/python_course_doc
This commit is contained in:
commit
5b32090a1d
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,56 @@
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
|
def load_file(filename):
|
||||||
|
"""
|
||||||
|
We load a file and make a list out of it. Note that the same function is
|
||||||
|
used for both files (both adjectives and subjects). Functions should be
|
||||||
|
made as generic as possible.
|
||||||
|
|
||||||
|
There IS a problem you can fix, some logins will have spaces in them. Try
|
||||||
|
to remove them in this function!
|
||||||
|
"""
|
||||||
|
words = []
|
||||||
|
with open(filename, "r") as fp:
|
||||||
|
lines = fp.readlines()
|
||||||
|
for line in lines:
|
||||||
|
words.append(line.strip()) # what does strip() do, what does append() do? remember CTRL+Q!
|
||||||
|
return words
|
||||||
|
|
||||||
|
|
||||||
|
def generate_username():
|
||||||
|
"""
|
||||||
|
We'll generate a random pair of adjectives and subjects from two wordlists.
|
||||||
|
You NEED to have both files in you python project for this to work! Note
|
||||||
|
the capitalize method call to make it all prettier...
|
||||||
|
"""
|
||||||
|
adjectives = load_file("./adjectives.txt")
|
||||||
|
subjects = load_file("./subjects.txt")
|
||||||
|
adjective = random.choice(adjectives)
|
||||||
|
subject = random.choice(subjects)
|
||||||
|
username = adjective.capitalize() + subject.capitalize()
|
||||||
|
return username
|
||||||
|
|
||||||
|
|
||||||
|
def generate_password(length=10, complictated=True):
|
||||||
|
"""
|
||||||
|
We generate a password with default settings. You can overide these by
|
||||||
|
changing the arguments in the function call.
|
||||||
|
"""
|
||||||
|
password = ""
|
||||||
|
if complictated:
|
||||||
|
chars = string.ascii_letters + string.digits + string.punctuation
|
||||||
|
else:
|
||||||
|
chars = string.ascii_letters
|
||||||
|
for i in range(0, length):
|
||||||
|
password += random.choice(chars)
|
||||||
|
return password
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# let's do some testing!
|
||||||
|
username_test = generate_username()
|
||||||
|
print(username_test)
|
||||||
|
password_test = generate_password()
|
||||||
|
print(password_test)
|
|
@ -0,0 +1,61 @@
|
||||||
|
import login_generator
|
||||||
|
|
||||||
|
|
||||||
|
def prompt():
|
||||||
|
"""
|
||||||
|
We prompt but you KNOW how this works!
|
||||||
|
"""
|
||||||
|
response = ""
|
||||||
|
while not response.isdigit():
|
||||||
|
response = input("how many login pairs would you like to create?")
|
||||||
|
return int(response)
|
||||||
|
|
||||||
|
|
||||||
|
def how_long():
|
||||||
|
"""
|
||||||
|
And again... (we could combine both prompts, but how?)
|
||||||
|
"""
|
||||||
|
response = ""
|
||||||
|
while not response.isdigit():
|
||||||
|
response = input("how long should the password be?")
|
||||||
|
return int(response)
|
||||||
|
|
||||||
|
|
||||||
|
def complex_or_not():
|
||||||
|
response = ""
|
||||||
|
while response.lower() not in ["y", "n"]:
|
||||||
|
response = input("you want complex passwords? (y/n)")
|
||||||
|
if response.lower() == "y":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def create_login(length, complicated):
|
||||||
|
"""
|
||||||
|
We use our library to generate the username and password. The double return
|
||||||
|
might look confusing but just look at the for loop in the generate_logins
|
||||||
|
functions and you'll see how it unpacks...
|
||||||
|
"""
|
||||||
|
username = login_generator.generate_username()
|
||||||
|
password = login_generator.generate_password(length, complicated)
|
||||||
|
return username, password
|
||||||
|
|
||||||
|
|
||||||
|
def generate_logins(number, length, complicated):
|
||||||
|
"""
|
||||||
|
Easy no? But what does the i do? Do we really need it's value?
|
||||||
|
"""
|
||||||
|
for i in range(0, number):
|
||||||
|
username, password = create_login(length, complicated)
|
||||||
|
print("username {}: {}".format(i, username))
|
||||||
|
print("password {}: {}".format(i, password))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Here we go!
|
||||||
|
number_of_logins = prompt()
|
||||||
|
complicted = complex_or_not()
|
||||||
|
length = how_long()
|
||||||
|
generate_logins(number_of_logins, length, complicted)
|
||||||
|
|
|
@ -0,0 +1,239 @@
|
||||||
|
Aardvark
|
||||||
|
African elephant
|
||||||
|
Albatross
|
||||||
|
Alley cat
|
||||||
|
Alligator
|
||||||
|
Amphibian
|
||||||
|
Ant
|
||||||
|
Anteater
|
||||||
|
Antelope
|
||||||
|
Ape
|
||||||
|
Armadillo
|
||||||
|
Asian elephant
|
||||||
|
Baboon
|
||||||
|
Badger
|
||||||
|
Bat
|
||||||
|
Bear
|
||||||
|
Beaver
|
||||||
|
Beetle
|
||||||
|
Billy goat
|
||||||
|
Bison
|
||||||
|
Boar
|
||||||
|
Bobcat
|
||||||
|
Bovine
|
||||||
|
Bronco
|
||||||
|
Buck
|
||||||
|
Buffalo
|
||||||
|
Bug
|
||||||
|
Bull
|
||||||
|
Bunny
|
||||||
|
BunnyCalf
|
||||||
|
Camel
|
||||||
|
Canary
|
||||||
|
Canine
|
||||||
|
Caribou
|
||||||
|
Cat
|
||||||
|
Caterpillar
|
||||||
|
Centipede
|
||||||
|
Chanticleer
|
||||||
|
Cheetah
|
||||||
|
Chick
|
||||||
|
Chimpanzee
|
||||||
|
Chinchilla
|
||||||
|
Chipmunk
|
||||||
|
Clam
|
||||||
|
Cockatiel
|
||||||
|
Colt
|
||||||
|
Condor
|
||||||
|
Cougar
|
||||||
|
Cow
|
||||||
|
Coyote
|
||||||
|
Crab
|
||||||
|
Crane
|
||||||
|
Creature
|
||||||
|
Crocodile
|
||||||
|
Crow
|
||||||
|
Cub
|
||||||
|
Cur
|
||||||
|
Cygnet
|
||||||
|
Deer
|
||||||
|
Dingo
|
||||||
|
Dodo
|
||||||
|
Doe
|
||||||
|
Dog
|
||||||
|
Dolphin
|
||||||
|
Donkey
|
||||||
|
Dove
|
||||||
|
Drake
|
||||||
|
Duck
|
||||||
|
Eagle
|
||||||
|
Egret
|
||||||
|
Elephant
|
||||||
|
Elk
|
||||||
|
Emu
|
||||||
|
Ewe
|
||||||
|
Falcon
|
||||||
|
Fawn
|
||||||
|
Feline
|
||||||
|
Ferret
|
||||||
|
Flamingo
|
||||||
|
Flee
|
||||||
|
Flies
|
||||||
|
Foal
|
||||||
|
Fowl
|
||||||
|
Fox
|
||||||
|
Frog
|
||||||
|
Gander
|
||||||
|
Gazelle
|
||||||
|
Gelding
|
||||||
|
Gerbil
|
||||||
|
Gibbon
|
||||||
|
Giraffe
|
||||||
|
Goat
|
||||||
|
Goose
|
||||||
|
Gopher
|
||||||
|
Gorilla
|
||||||
|
Grizzly bear
|
||||||
|
Guinea pig
|
||||||
|
Hamster
|
||||||
|
Hare
|
||||||
|
Hawk
|
||||||
|
Hedgehog
|
||||||
|
Heifer
|
||||||
|
Hippopotamus
|
||||||
|
Horse
|
||||||
|
Hound
|
||||||
|
Hummingbird
|
||||||
|
Hyena
|
||||||
|
Ibis
|
||||||
|
Iguana
|
||||||
|
Jackal
|
||||||
|
Jackrabbit
|
||||||
|
Jaguar
|
||||||
|
Javalina
|
||||||
|
Jellyfish
|
||||||
|
Jenny
|
||||||
|
Joey
|
||||||
|
Kangaroo
|
||||||
|
Kid
|
||||||
|
Kitten
|
||||||
|
Kiwi
|
||||||
|
Koala
|
||||||
|
Komodo dragon
|
||||||
|
Krill
|
||||||
|
Lamb
|
||||||
|
Lemming
|
||||||
|
Lemur
|
||||||
|
Leopard
|
||||||
|
Lion
|
||||||
|
Lioness
|
||||||
|
Llama
|
||||||
|
Lobster
|
||||||
|
Lynx
|
||||||
|
Macaw
|
||||||
|
Manatee
|
||||||
|
Marmoset
|
||||||
|
Marmot
|
||||||
|
Mink
|
||||||
|
Minnow
|
||||||
|
Mite
|
||||||
|
Mockingbird
|
||||||
|
Mole
|
||||||
|
Mongoose
|
||||||
|
Mongrel
|
||||||
|
Monkey
|
||||||
|
Moose
|
||||||
|
Mouse
|
||||||
|
Mule
|
||||||
|
Mustang
|
||||||
|
Mutt
|
||||||
|
Nag
|
||||||
|
Narwhale
|
||||||
|
Newt
|
||||||
|
Ocelot
|
||||||
|
Octopus
|
||||||
|
Opossum
|
||||||
|
Orangutan
|
||||||
|
Orca
|
||||||
|
Osprey
|
||||||
|
Ostrich
|
||||||
|
Otter
|
||||||
|
Owl
|
||||||
|
Ox
|
||||||
|
Pachyderm
|
||||||
|
Panda
|
||||||
|
Panther
|
||||||
|
Parakeet
|
||||||
|
Parrot
|
||||||
|
Peacock
|
||||||
|
Pelican
|
||||||
|
Penguin
|
||||||
|
Pheasant
|
||||||
|
Pig
|
||||||
|
Pigeon
|
||||||
|
Piglet
|
||||||
|
Platypus
|
||||||
|
Pony
|
||||||
|
Pooch
|
||||||
|
Porcupine
|
||||||
|
Porpoise
|
||||||
|
Primate
|
||||||
|
Puppy
|
||||||
|
Pussycat
|
||||||
|
Rabbit
|
||||||
|
Raccoon
|
||||||
|
Ram
|
||||||
|
Rat
|
||||||
|
Reptiles
|
||||||
|
Rhinoceros
|
||||||
|
Robin
|
||||||
|
Rooster
|
||||||
|
Salamander
|
||||||
|
Sea lion
|
||||||
|
Seagull
|
||||||
|
Seal
|
||||||
|
Sheep
|
||||||
|
Sidewinder
|
||||||
|
Skunk
|
||||||
|
Sloth
|
||||||
|
Snail
|
||||||
|
Snake
|
||||||
|
Songbird
|
||||||
|
Sow
|
||||||
|
Spider
|
||||||
|
Squid
|
||||||
|
Squirrel
|
||||||
|
Stallion
|
||||||
|
Steer
|
||||||
|
Stork
|
||||||
|
Stork
|
||||||
|
Swan
|
||||||
|
Tadpole
|
||||||
|
Tapir
|
||||||
|
Terrapin
|
||||||
|
Thoroughbred
|
||||||
|
Tiger
|
||||||
|
Toad
|
||||||
|
Tortoise
|
||||||
|
Toucan
|
||||||
|
Turkey
|
||||||
|
Uakari
|
||||||
|
Unicorn
|
||||||
|
Vixen
|
||||||
|
Vole
|
||||||
|
Vulture
|
||||||
|
Wallaby
|
||||||
|
Walrus
|
||||||
|
Warthog
|
||||||
|
Wasp
|
||||||
|
Weasel
|
||||||
|
Whale
|
||||||
|
Wildebeast
|
||||||
|
Wolf
|
||||||
|
Wombat
|
||||||
|
Woodpecker
|
||||||
|
Worm
|
||||||
|
X-ray fish
|
||||||
|
Yak
|
||||||
|
Zebra
|
||||||
|
|
|
@ -1072,67 +1072,815 @@ There are a couple of things you should definitely read up on.
|
||||||
|
|
||||||
# While loop
|
# While loop
|
||||||
|
|
||||||
TODO guess the number exercise
|
We started our python journey with fully linear code.
|
||||||
|
Next we saw functions which are first **defined** and called afterwards.
|
||||||
|
Now we'll have a look at **loops**.
|
||||||
|
In python there are **two** types of loops, a **while** and a **for** loop.
|
||||||
|
We'll start with the while loop which I see as a loop in *time*.
|
||||||
|
The for loop is a loop in *space* but we'll get to that one later.
|
||||||
|
|
||||||
|
The concept of a while loop is pretty simple.
|
||||||
|
Code **within** the loop will be executed as long as a **condition** is met.
|
||||||
|
Consider the code below.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import time
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
print("before the loop, counter: {}".format(counter))
|
||||||
|
|
||||||
|
while counter <= 10:
|
||||||
|
print("inside the loop, counter: {}".format(counter))
|
||||||
|
counter += 1
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
print("after the loop, counter: {}".format(counter))
|
||||||
|
```
|
||||||
|
|
||||||
|
Two *extra* things might look new to you here.
|
||||||
|
First the `import time` and `time.sleep(1)`, can you tell me what it does?
|
||||||
|
Next the `counter += 1` which is called [incrementing](https://stackoverflow.com/questions/1485841/behaviour-of-increment-and-decrement-operators-in-python).
|
||||||
|
You'll find this feature in most languages.
|
||||||
|
You can think of it's syntax as *counter equals itself plus 1*.
|
||||||
|
The *1* can be any number you want though!
|
||||||
|
|
||||||
|
When learning the `while` [keyword](https://docs.python.org/3/reference/compound_stmts.html#the-while-statement) there is a *second* keyword you should learn.
|
||||||
|
It comes in very handy when constructing [infinite loops](https://en.wikipedia.org/wiki/Infinite_loop).
|
||||||
|
Consider the following code.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import time
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
print("before the loop, counter: {}".format(counter))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
print("inside the loop, counter: {}".format(counter))
|
||||||
|
counter += 1
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
print("after the loop, counter: {}".format(counter))
|
||||||
|
```
|
||||||
|
|
||||||
|
The `while True` condition is *always* `True` so the loop will **never** exit!
|
||||||
|
This is what we call an infinite loop.
|
||||||
|
The `break` keyword was added to the language so we can *break out* of a loop.
|
||||||
|
The logic is as follows.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import time
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
print("before the loop, counter: {}".format(counter))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
print("inside the loop, counter: {}".format(counter))
|
||||||
|
counter += 1
|
||||||
|
if counter >= 10:
|
||||||
|
print("I'll break now!")
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
print("after the loop, counter: {}".format(counter))
|
||||||
|
```
|
||||||
|
|
||||||
|
Infinite loops are a cornerstone of modern programming.
|
||||||
|
While they might look scary, don't overthink it, you'll get used to them very quickly.
|
||||||
|
|
||||||
|
⛑ **When testing out an infinite loop it's sometimes handy to insert a `time.sleep` in it to slow down the execution a bit so you can wrap your head around what's happening.**
|
||||||
|
|
||||||
|
🏃 Try it
|
||||||
|
---
|
||||||
|
|
||||||
|
Go back to the Celsius to Farenheit converter and add a while loop to ensure the user put's in only numbers.
|
||||||
|
|
||||||
|
|
||||||
|
# Coding challenge - Guess the number
|
||||||
|
|
||||||
|
Now that you know how to repeat code execution we can create our first game!
|
||||||
|
Everybody knows the *guess the number* game.
|
||||||
|
The computer chooses a *random* number and the user has to *guess* which number it is.
|
||||||
|
At each try the computer will till you if the user's number is bigger or smaller *than* the one the computer has in mind.
|
||||||
|
The flow of the game could be as follows.
|
||||||
|
|
||||||
|
```
|
||||||
|
I have a number in mind...
|
||||||
|
What's your guess? 50
|
||||||
|
my number is bigger
|
||||||
|
What's your guess? 80
|
||||||
|
my number is smaller
|
||||||
|
What's your guess? blabla
|
||||||
|
that's not a number! try again...
|
||||||
|
What's your guess? 76
|
||||||
|
yes, that's right! you win!
|
||||||
|
bye bye...
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Spoiler warning</summary>
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
def ask_for_number():
|
||||||
|
result = input("What's your guess? ")
|
||||||
|
if result.isdigit():
|
||||||
|
number = int(result)
|
||||||
|
return number
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
number_to_guess = random.randint(0, 100)
|
||||||
|
print("I have a number in mind...")
|
||||||
|
while True:
|
||||||
|
user_number = ask_for_number()
|
||||||
|
if user_number is None:
|
||||||
|
print("that's not a number! try again...")
|
||||||
|
continue
|
||||||
|
elif number_to_guess == user_number:
|
||||||
|
print("yes, that's right! you win!")
|
||||||
|
break
|
||||||
|
elif number_to_guess > user_number:
|
||||||
|
print("my number is bigger")
|
||||||
|
elif number_to_guess < user_number:
|
||||||
|
print("my number is smaller")
|
||||||
|
print("bye bye...")
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
🏃 Try it
|
||||||
|
---
|
||||||
|
|
||||||
|
My *solution* is very basic.
|
||||||
|
Think of some ways to improve on it.
|
||||||
|
Can you limit the number of tries?
|
||||||
|
Can you add a feature to let the user play a *second* game after he/she wins or loses?
|
||||||
|
Coming up with challenges is on of the most *challenging* aspect op learning how to program.
|
||||||
|
Your thought process will send you of into unknown territory and will force you to expand you knowledge.
|
||||||
|
We'll get back to this thought process later, but if you feel like an extra challenge go for it!
|
||||||
|
|
||||||
# Lists
|
# Lists
|
||||||
|
|
||||||
|
The different built-in objects we've seen until now, such as `str` and `int` are simple [text](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str) and [numeric](https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex) types.
|
||||||
|
There are other classes of objects that server different purposes.
|
||||||
|
One of these *groups* is called [sequence types](https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range).
|
||||||
|
|
||||||
|
A list in python is pretty much exactly what you think it is.
|
||||||
|
It is an *object* that groups together *other* objects.
|
||||||
|
Sounds complicated?
|
||||||
|
Have a look at the following.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
my_numbers = [1, 2, 44, 60, 70]
|
||||||
|
print(my_numbers)
|
||||||
|
```
|
||||||
|
|
||||||
|
Easy right?
|
||||||
|
Compared to [other languages](https://www.cplusplus.com/reference/list/list/) lists in python are *very* flexible.
|
||||||
|
They can contain objects of different types, and their length can be changed at any time.
|
||||||
|
Programmers coming from other languages often find this flexibility of python a bug but you should see it as a feature.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
favorite_number = 7
|
||||||
|
name = "wouter"
|
||||||
|
date = [1986, 10, 7]
|
||||||
|
values = [1, date, favorite_number, "hello world", name]
|
||||||
|
|
||||||
|
print(values)
|
||||||
|
```
|
||||||
|
|
||||||
|
The code above is just an illustration of the flexibility of lists.
|
||||||
|
|
||||||
## Creating lists
|
## Creating lists
|
||||||
|
|
||||||
## Picking elements
|
Creating lists can be done in two ways, either by using the **square brackets** `[]` or by calling `list`.
|
||||||
|
When calling `list` it takes **one argument**, which python will iterate over.
|
||||||
|
For example:
|
||||||
|
|
||||||
## Slicing lists
|
```python3
|
||||||
|
>>> first_list = ["hello", "world", "!"]
|
||||||
|
>>> first_list
|
||||||
|
['hello', 'world', '!']
|
||||||
|
>>> second_list = list("hello world !")
|
||||||
|
>>> second_list
|
||||||
|
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', ' ', '!']
|
||||||
|
>>>
|
||||||
|
```
|
||||||
|
|
||||||
|
## List methods
|
||||||
|
|
||||||
|
As a `list` is a different type of object, it has different methods you can invoke on it.
|
||||||
|
When using tab complete in the python shell we get the following.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
>>> second_list.
|
||||||
|
second_list.append( second_list.count( second_list.insert( second_list.reverse(
|
||||||
|
second_list.clear( second_list.extend( second_list.pop( second_list.sort(
|
||||||
|
second_list.copy( second_list.index( second_list.remove(
|
||||||
|
>>> second_list.
|
||||||
|
```
|
||||||
|
|
||||||
|
One of the most used methods is `append`.
|
||||||
|
It is used to add an element to the end of the list.
|
||||||
|
The second most used method is the `pop` one.
|
||||||
|
Read the shell code below and you'll understand immediately what they do.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
>>> first_list
|
||||||
|
['hello', 'world', '!']
|
||||||
|
>>> first_list.append("coucou")
|
||||||
|
>>> first_list
|
||||||
|
['hello', 'world', '!', 'coucou']
|
||||||
|
>>> first_list.pop()
|
||||||
|
'coucou'
|
||||||
|
>>> first_list
|
||||||
|
['hello', 'world', '!']
|
||||||
|
>>>
|
||||||
|
```
|
||||||
|
|
||||||
|
🏃 Try it
|
||||||
|
---
|
||||||
|
|
||||||
|
Look at all the methods you can invoke on a list and try them out.
|
||||||
|
Remember to read the documentation!
|
||||||
|
|
||||||
|
## Picking elements and slicing lists
|
||||||
|
|
||||||
|
We can pick elements from the list of slice the list as we please.
|
||||||
|
A code block speaks more than words.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
>>> long_list
|
||||||
|
['I', 'am', 'a', 'very', 'long', 'list', 'of', 'words', 'that', 'make', 'little', 'actual', 'sense']
|
||||||
|
>>> long_list[7]
|
||||||
|
'words'
|
||||||
|
>>> long_list[7:9]
|
||||||
|
['words', 'that']
|
||||||
|
>>> long_list[7:]
|
||||||
|
['words', 'that', 'make', 'little', 'actual', 'sense']
|
||||||
|
>>> long_list[:7]
|
||||||
|
['I', 'am', 'a', 'very', 'long', 'list', 'of']
|
||||||
|
>>> long_list[-1]
|
||||||
|
'sense'
|
||||||
|
>>> long_list[0]
|
||||||
|
'I'
|
||||||
|
>>>
|
||||||
|
```
|
||||||
|
|
||||||
|
⛑ **In programming we start counting at 0 because 0 and nothing are not the same thing.**
|
||||||
|
|
||||||
|
🏃 Try it
|
||||||
|
---
|
||||||
|
|
||||||
|
Slice and dice away!
|
||||||
|
A handy method of the `str` class is `split` which will cut up a string into separate elements.
|
||||||
|
The result will be a `list` on which you can use `list` methods.
|
||||||
|
|
||||||
# For loop
|
# For loop
|
||||||
|
|
||||||
TODO say hello to my friends exercise
|
I mentioned the for loop, which is a loop in space, when we saw the `while` loop.
|
||||||
TODO simple ROT13 cryptography with multiple libs
|
The [keyword](https://docs.python.org/3/reference/compound_stmts.html#the-for-statement) in question is, surprise surprise, `for`!
|
||||||
|
I see it as a loop in space because it will run *for each element in a sequence* which in my mind is something of substance.
|
||||||
|
Your logical mileage may vary but as long as you understand the following code block we're good.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import time
|
||||||
|
|
||||||
|
friends = ["max", "mike", "alice", "steve", "rosa", "hans"]
|
||||||
|
|
||||||
|
print("The door opens and in walk my {} friends!".format(len(friends)))
|
||||||
|
|
||||||
|
for friend in friends:
|
||||||
|
print("Hello {}!".format(friend.capitalize()))
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
print("{} closes the door behind him...".format(friend.capitalize()))
|
||||||
|
```
|
||||||
|
|
||||||
# Coding challenge - Cheerleader chant
|
# Coding challenge - Cheerleader chant
|
||||||
|
|
||||||
TODO nested for loop exercise
|
Can you make me a program that outputs this type of cheerleader chant?
|
||||||
|
You can make it *prettier* by importing your `pretty_print` function, plus you can add some `time.sleep` in it to make it more *musical*.
|
||||||
|
|
||||||
|
```
|
||||||
|
Give me an m
|
||||||
|
M
|
||||||
|
Give me an a
|
||||||
|
A
|
||||||
|
Give me an x
|
||||||
|
X
|
||||||
|
Gooooooooo, MAX!
|
||||||
|
Give me an m
|
||||||
|
M
|
||||||
|
Give me an i
|
||||||
|
I
|
||||||
|
Give me an k
|
||||||
|
K
|
||||||
|
Give me an e
|
||||||
|
E
|
||||||
|
Gooooooooo, MIKE!
|
||||||
|
Give me an c
|
||||||
|
C
|
||||||
|
Give me an a
|
||||||
|
A
|
||||||
|
Give me an m
|
||||||
|
M
|
||||||
|
Give me an i
|
||||||
|
I
|
||||||
|
Give me an l
|
||||||
|
L
|
||||||
|
Give me an l
|
||||||
|
L
|
||||||
|
Give me an e
|
||||||
|
E
|
||||||
|
Gooooooooo, CAMILLE!
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Spoiler warning</summary>
|
||||||
|
|
||||||
|
```python3
|
||||||
|
friends = ["max", "mike", "camille"]
|
||||||
|
|
||||||
|
|
||||||
|
for friend in friends:
|
||||||
|
for letter in friend:
|
||||||
|
print("Give me an {}".format(letter))
|
||||||
|
print("{}".format(letter.upper()))
|
||||||
|
print("Gooooooooo, {}!".format(friend.upper()))
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
# Coding challenge - ROT13
|
||||||
|
|
||||||
|
ROT13 is one of the oldest cryptographic cyphers know to mankind.
|
||||||
|
It dates back to the Roman empire and is also known as a [Caesar cypher](https://en.wikipedia.org/wiki/Caesar_cipher).
|
||||||
|
The algorithm is pretty simple, you just shift a letter 13 places in the alphabet so `a` becomes `n` or `x` becomes `k`.
|
||||||
|
Have a look at [this](https://rot13.com/) website to see the cypher in action.
|
||||||
|
Now, can you make a program that encrypts a phrase with ROT13?
|
||||||
|
Something along these lines:
|
||||||
|
|
||||||
|
```python3
|
||||||
|
What's your secret? hello world!
|
||||||
|
encoded secret: uryyb jbeyq!
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Spoiler warning</summary>
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
|
def encode_rot(msg, rot=13):
|
||||||
|
msg = msg.lower()
|
||||||
|
letters = list(string.ascii_lowercase)
|
||||||
|
coded_msg = []
|
||||||
|
for letter in msg:
|
||||||
|
if letter not in letters:
|
||||||
|
coded_msg.append(letter)
|
||||||
|
else:
|
||||||
|
idx = letters.index(letter) + rot
|
||||||
|
coded_letter = letters[idx % len(letters)]
|
||||||
|
coded_msg.append(coded_letter)
|
||||||
|
coded_msg = "".join(coded_msg)
|
||||||
|
return coded_msg
|
||||||
|
|
||||||
|
|
||||||
|
def decode_rot(msg, rot=13):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
clear_message = input("What's your secret? ")
|
||||||
|
encoded_message = encode_rot(clear_message)
|
||||||
|
print("encoded secret: {}".format(encoded_message))
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
🏃 Try it
|
||||||
|
---
|
||||||
|
|
||||||
|
To make things more interesting you can add a decode function.
|
||||||
|
Plus you could add a prompt that asks how big the shift should be (ROT13, ROT16, ...).
|
||||||
|
|
||||||
|
# List comprehension
|
||||||
|
|
||||||
|
This is a bit of an advanced topic but I'm putting it here to show you a very unique and powerful feature of python.
|
||||||
|
It's an *in-line* combination of `list`, `for` and conditional logic which allows us to make lists of lists which obey certain conditions.
|
||||||
|
You can [learn](https://12ft.io/proxy?q=https%3A%2F%2Frealpython.com%2Flist-comprehension-python%2F) about it online.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
mixed_list = ["one", "2", "three", "4", "5", "six6", "se7en", "8"]
|
||||||
|
|
||||||
|
digits = [d for d in mixed_list if d.isdigit()]
|
||||||
|
|
||||||
|
print(digits)
|
||||||
|
```
|
||||||
|
|
||||||
|
The code above can be recreated **without** list comprehension as well, it will just be *a lot* longer.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
mixed_list = ["one", "2", "three", "4", "5", "six6", "se7en", "8"]
|
||||||
|
|
||||||
|
digits = []
|
||||||
|
for d in mixed_list:
|
||||||
|
if d.isdigit():
|
||||||
|
digits.append(d)
|
||||||
|
|
||||||
|
print(digits)
|
||||||
|
```
|
||||||
|
|
||||||
|
As the `d` in the list comprehension is **always** a digit, we can convert it to an integer on the spot!
|
||||||
|
|
||||||
|
```python3
|
||||||
|
mixed_list = ["one", "2", "three", "4", "5", "six6", "se7en", "8"]
|
||||||
|
|
||||||
|
digits = [int(d) for d in mixed_list if d.isdigit()]
|
||||||
|
|
||||||
|
print(digits)
|
||||||
|
```
|
||||||
|
|
||||||
# Handling files
|
# Handling files
|
||||||
|
|
||||||
|
When we `import` a library python will read and execute the file in question.
|
||||||
|
We can also just *read* a simple text file and *use* the data that's in the file.
|
||||||
|
There are two ways of reading a file, one more *pythonic* and one more linear.
|
||||||
|
I'll outline both and you can use whichever seems more logical to you.
|
||||||
|
|
||||||
## Reading from a file
|
## Reading from a file
|
||||||
|
|
||||||
|
### In-line way
|
||||||
|
|
||||||
|
The builtin function `open` is what's new here.
|
||||||
|
It takes two arguments, one is the [path](https://en.wikipedia.org/wiki/Path_(computing)) and the other is a *mode*.
|
||||||
|
The most used modes are **read** or **write**, and this as either **text** or **binary**.
|
||||||
|
Have a look at the documentation to discover more modes.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
fp = open("./examples/data.txt", "r")
|
||||||
|
data = fp.readlines()
|
||||||
|
print("file contains: {}".format(data))
|
||||||
|
fp.close()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pythonic way
|
||||||
|
|
||||||
|
The *exact* same thing can be done in a more pythonic way as follows.
|
||||||
|
The beauty of the `with` syntax is that the `close` function call is implied by the indentation.
|
||||||
|
I personally prefer this way of reading and writing files but you do you!
|
||||||
|
|
||||||
|
```python3
|
||||||
|
file_to_open = "./examples/data.txt"
|
||||||
|
|
||||||
|
with open(file_to_open, "r") as fp:
|
||||||
|
data = fp.readlines()
|
||||||
|
print("file contains: {}".format(data))
|
||||||
|
|
||||||
|
print("{} has {} lines".format(file_to_open, len(data)))
|
||||||
|
```
|
||||||
|
|
||||||
## Writing to a file
|
## Writing to a file
|
||||||
|
|
||||||
## csv, JSON and yaml
|
Writing to a file can also be done in two ways, a pythonic and *less* pythonic way.
|
||||||
|
As I prefer the pythonic way I'll only showcase that one but you'll be able to easily adapt the code yourself.
|
||||||
|
The only difference is the **mode** we use to `open` the file.
|
||||||
|
|
||||||
## pickle
|
```python3
|
||||||
|
first_name = input("what's your first name? ")
|
||||||
|
last_name = input("what's your last name? ")
|
||||||
|
birthday = input("what's your date of birth? ")
|
||||||
|
|
||||||
|
data = [first_name, last_name, birthday]
|
||||||
|
|
||||||
|
file_to_open = "./examples/test.tmp"
|
||||||
|
|
||||||
|
with open(file_to_open, "w") as fp:
|
||||||
|
for element in data:
|
||||||
|
fp.write("{}\n".format(element))
|
||||||
|
print("done!")
|
||||||
|
```
|
||||||
|
|
||||||
|
There is also a way to write a batch of lines to a file in one go.
|
||||||
|
This is done as follows.
|
||||||
|
But, you'll notice there is no **newline** added after each element.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
data = ["wouter", "gordts", "1986"]
|
||||||
|
|
||||||
|
file_to_open = "./examples/test.tmp"
|
||||||
|
|
||||||
|
with open(file_to_open, "w") as fp:
|
||||||
|
fp.writelines(data)
|
||||||
|
```
|
||||||
|
|
||||||
# Coding challenge - Login generator
|
# Coding challenge - Login generator
|
||||||
|
|
||||||
TODO write a login generator as a library with a cli as program
|
Can you write me a program that creates random, but easy to remember, usernames?
|
||||||
BONUS argparse, save to file, read from file
|
Plus, for each username also a *not-so-easy-to-remember* password?
|
||||||
|
Maybe with a bit of flexibility?
|
||||||
|
For example variable password length?
|
||||||
|
|
||||||
|
This is an exercise you can take pretty far if you plan it out properly.
|
||||||
|
I would advise you to write the **generator** functions as a library.
|
||||||
|
Then import those functions into the program where you implement the user facing logic.
|
||||||
|
By doing so you can reuse your code for multiple interfaces (CLI, TUI, [argparse](https://docs.python.org/3/howto/argparse.html)).
|
||||||
|
If you want to you can also **save** your logins to a file!
|
||||||
|
|
||||||
|
An example of the output I expect:
|
||||||
|
|
||||||
|
```
|
||||||
|
how many login pairs would you like to create?3
|
||||||
|
you want complex passwords? (y/n)y
|
||||||
|
how long should the password be?32
|
||||||
|
username 0: EarnestCrocodile
|
||||||
|
password 0: :sdGV&[FDYZZ|RXUpZeo`J&t@*Z>^fEW
|
||||||
|
username 1: AbstractedDragon
|
||||||
|
password 1: 32hz5&C@<o\OMa9tnET(lk(3wF%d?$Dy
|
||||||
|
username 2: MeekStallion
|
||||||
|
password 2: +;^di8a":AD;_b4^w$Fj'RVkI`CoG,LX
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Spoiler warning</summary>
|
||||||
|
|
||||||
|
This spoiler warning is in multiple steps.
|
||||||
|
If you're unsure how to generate the *random-yet-easy-to-remember* have a look at [this file](./assets/subjects.txt) and [this file](./assets/adjectives.txt).
|
||||||
|
|
||||||
|
**Stop here and try it out!**
|
||||||
|
|
||||||
|
If you're unsure how to tackle the *library part* of this exercise, have a look at [this file](./assets/login_generator.py).
|
||||||
|
Don't just copy this code, read it and recreate it yourself!
|
||||||
|
|
||||||
|
**Stop here and try it out!**
|
||||||
|
|
||||||
|
Once the library is done you can code the *interface*.
|
||||||
|
For some inspiration for a simple question/response system you can have a look [here](./assets/pwd_cli.py).
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
# Dictionaries as data containers
|
# Dictionaries as data containers
|
||||||
|
|
||||||
TODO adapt the login generator to output a dict
|
Of the *built-in* types we first say `str`, `int` and `float`.
|
||||||
|
Next we saw *sequence* types such as `list` and `tupple`.
|
||||||
|
Now we'll dive into a **mapping type** called `dict`.
|
||||||
|
I advise you to have a look at the [reference pages](https://docs.python.org/3/library/stdtypes.html#mapping-types-dict) when in doubt.
|
||||||
|
|
||||||
# Creating our own classes
|
A dictionary is *kind* of like a list but it has **two** objects per **element**.
|
||||||
|
We call them **key** and **value**.
|
||||||
|
There are a couple of rules you need to be aware of though.
|
||||||
|
|
||||||
## Class examples
|
1. In a `dict` the keys have to be **unique**.
|
||||||
|
2. A dictionary is **unordered** meaning the *first* element is not garanteed to remain the first over the lifespan of the dictionary.
|
||||||
|
3. The keys used must be **hashable**.
|
||||||
|
|
||||||
|
Let's visualize a legal dictionary!
|
||||||
|
It's declared with **curly brackets** as follows `{}`.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
my_data = {"key": "value", "name": "wouter", "age": 35}
|
||||||
|
|
||||||
|
same_data_different_layout = {
|
||||||
|
"key": "value",
|
||||||
|
"name": "wouter",
|
||||||
|
"age": 35,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's have a look at the **methods** we can invoke on a `dict`.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
>>> my_data = {"key": "value", "name": "wouter", "age": 35,}
|
||||||
|
>>> my_data.
|
||||||
|
my_data.clear( my_data.get( my_data.pop( my_data.update(
|
||||||
|
my_data.copy( my_data.items( my_data.popitem( my_data.values(
|
||||||
|
my_data.fromkeys( my_data.keys( my_data.setdefault(
|
||||||
|
>>> my_data.keys()
|
||||||
|
dict_keys(['key', 'name', 'age'])
|
||||||
|
>>> my_data.values()
|
||||||
|
dict_values(['value', 'wouter', 35])
|
||||||
|
>>> my_data.items()
|
||||||
|
dict_items([('key', 'value'), ('name', 'wouter'), ('age', 35)])
|
||||||
|
>>> for key, value in my_data.items():
|
||||||
|
... print("key is {}".format(key))
|
||||||
|
... print("value is {}".format(value))
|
||||||
|
...
|
||||||
|
key is key
|
||||||
|
value is value
|
||||||
|
key is name
|
||||||
|
value is wouter
|
||||||
|
key is age
|
||||||
|
value is 35
|
||||||
|
>>>
|
||||||
|
```
|
||||||
|
|
||||||
|
We can reference specific **values** corresponding to specific **keys** as follows.
|
||||||
|
|
||||||
|
```pythons
|
||||||
|
>>> my_data["name"]
|
||||||
|
'wouter'
|
||||||
|
>>> my_data["age"]
|
||||||
|
35
|
||||||
|
>>>
|
||||||
|
```
|
||||||
|
|
||||||
|
We can use dictionaries as data containers and put them in a list to group together similar data elements.
|
||||||
|
The code below should explain it quite nicely.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
login_ovh = {"username": "EarnestCrocodile", "password": ":sdGV&[FDYZZ|RXUpZeo`J&t@*Z>^fEW"}
|
||||||
|
login_mailbox = {"username": "AbstractedDragon", "password": "32hz5&C@<o\OMa9tnET(lk(3wF%d?$Dy"}
|
||||||
|
login_gitea = {"username": "MeekStallion", "password": "+;^di8af:AD;_b4^w$Fj'RVkI`CoG,LX"}
|
||||||
|
|
||||||
|
my_login_list = [login_ovh, login_mailbox, login_gitea]
|
||||||
|
|
||||||
|
for login in my_login_list:
|
||||||
|
print("login {}".format(my_login_list.index(login)))
|
||||||
|
for key in login.keys():
|
||||||
|
print("\t{}: {}".format(key, login[key]))
|
||||||
|
```
|
||||||
|
|
||||||
|
# Coding challenge - Task manager
|
||||||
|
|
||||||
|
Can you create me a *task manager* please?
|
||||||
|
I made one that is run from the command line with different arguments to modify it's behaviour.
|
||||||
|
If this looks too challenging I can tell you that the *full code* is 64 lines long, including empty lines!
|
||||||
|
Those of you who already tried out [argparse](https://realpython.com/command-line-interfaces-python-argparse/) in the previous challenges will probably understand what's going on here.
|
||||||
|
Those who did not I urge you to have a look at the link above and don't hesitate to ask for help!
|
||||||
|
|
||||||
|
```bash
|
||||||
|
➜ python_course_doc git:(master) ✗ python3 test.py --help
|
||||||
|
usage: test.py [-h] [--file FILE] {add,delete,show} ...
|
||||||
|
|
||||||
|
positional arguments:
|
||||||
|
{add,delete,show}
|
||||||
|
add adds a todo item to you todo list
|
||||||
|
delete deletes an item from your todo list
|
||||||
|
show show all your tasks
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--file FILE, -f FILE path to your todo file
|
||||||
|
➜ python_course_doc git:(master) ✗ python3 test.py show
|
||||||
|
ID: 0 --- buy milk
|
||||||
|
ID: 1 --- clean house
|
||||||
|
ID: 2 --- test my code
|
||||||
|
➜ python_course_doc git:(master) ✗ python3 test.py add write some documentation
|
||||||
|
➜ python_course_doc git:(master) ✗ python3 test.py show
|
||||||
|
ID: 0 --- buy milk
|
||||||
|
ID: 1 --- clean house
|
||||||
|
ID: 2 --- test my code
|
||||||
|
ID: 3 --- write some documentation
|
||||||
|
➜ python_course_doc git:(master) ✗ python3 test.py delete 2
|
||||||
|
➜ python_course_doc git:(master) ✗ python3 test.py show
|
||||||
|
ID: 0 --- buy milk
|
||||||
|
ID: 1 --- clean house
|
||||||
|
ID: 2 --- write some documentation
|
||||||
|
➜ python_course_doc git:(master) ✗
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Spoiler warning</summary>
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import argparse
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
|
||||||
|
def read_taskfile(taskfile_path):
|
||||||
|
tasks = []
|
||||||
|
if not pathlib.Path(taskfile_path).exists():
|
||||||
|
return tasks
|
||||||
|
with open(taskfile_path, "r") as fp:
|
||||||
|
lines = fp.readlines()
|
||||||
|
for line in lines:
|
||||||
|
task = line.strip()
|
||||||
|
tasks.append(task)
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
|
||||||
|
def write_taskfile(taskfile_path, tasks):
|
||||||
|
with open(taskfile_path, "w") as fp:
|
||||||
|
for task in tasks:
|
||||||
|
fp.write("{}\n".format(task))
|
||||||
|
|
||||||
|
|
||||||
|
def show_tasks(tasks):
|
||||||
|
counter = 0
|
||||||
|
for task in tasks:
|
||||||
|
print("ID: {} --- {}".format(counter, task))
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
|
||||||
|
def add_task(tasks, task):
|
||||||
|
tasks.append(task)
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
|
||||||
|
def delete_task(tasks, task_id):
|
||||||
|
tasks.pop(task_id)
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--file", "-f", default="./todo.tasks", help="path to your todo file")
|
||||||
|
subparser = parser.add_subparsers()
|
||||||
|
add = subparser.add_parser("add", help="adds a todo item to you todo list")
|
||||||
|
add.add_argument("task", nargs="*")
|
||||||
|
delete = subparser.add_parser("delete", help="deletes an item from your todo list")
|
||||||
|
delete.add_argument("idx", type=int, nargs="*")
|
||||||
|
show = subparser.add_parser("show", help="show all your tasks")
|
||||||
|
show.add_argument("show", action="store_true")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
taskfile = args.file
|
||||||
|
tasks = read_taskfile(taskfile)
|
||||||
|
|
||||||
|
if "task" in args:
|
||||||
|
tasks = add_task(tasks, " ".join(args.task))
|
||||||
|
write_taskfile(taskfile, tasks)
|
||||||
|
elif "idx" in args:
|
||||||
|
for idx in args.idx:
|
||||||
|
tasks = delete_task(tasks, idx)
|
||||||
|
write_taskfile(taskfile, tasks)
|
||||||
|
elif args.show:
|
||||||
|
show_tasks(tasks)
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
# Text based databases
|
||||||
|
|
||||||
|
The todo list example from before is handy but quite *limited* as a database.
|
||||||
|
As is it only holds one form or information and that is the *actual task*.
|
||||||
|
What if we want to add urgency or mark tasks complete (instead of deleting)?
|
||||||
|
This can be done by grouping data together.
|
||||||
|
We already saw a dictionaries which are good mapping structures but how can we save them to disk?
|
||||||
|
A hacky way would be to write a python file containing the `dict` and `import` it when we need it.
|
||||||
|
But there are better ways.
|
||||||
|
|
||||||
|
|
||||||
|
# Now for some useful scripting
|
||||||
|
|
||||||
|
With everything we have learned up until now you can start doing some interesting and useful things.
|
||||||
|
Have a look at [these exercises](https://gitea.86thumbs.net/waldek/linux_course_doc/src/branch/master/modules/qualifying/exercise_python.md).
|
||||||
|
You can try them out at your own pace.
|
||||||
|
I can give some hints or pointers if needed, either in class or individually.
|
||||||
|
Don't hesitate to ask for help!
|
||||||
|
|
||||||
|
# Creating our own objects
|
||||||
|
|
||||||
|
## First some *abstract* examples
|
||||||
|
|
||||||
TODO simple animal or vehicle exercise
|
TODO simple animal or vehicle exercise
|
||||||
TODO task manager
|
|
||||||
|
|
||||||
## Class inheritance
|
## Class inheritance
|
||||||
|
|
||||||
TODO shapes and surfaces
|
TODO shapes and surfaces
|
||||||
TODO superhero game
|
|
||||||
|
|
||||||
## Improve the login generator
|
## Now some *practical* improvements
|
||||||
|
|
||||||
|
### Improve the login generator
|
||||||
|
|
||||||
TODO convert the login generator to a class
|
TODO convert the login generator to a class
|
||||||
|
|
||||||
|
### Improve the task manager
|
||||||
|
|
||||||
|
TODO convert the task manager to a class
|
||||||
|
|
||||||
# Infinite programs
|
# Infinite programs
|
||||||
|
|
||||||
* insist on the nature of scripts we did up until now
|
* insist on the nature of scripts we did up until now
|
||||||
|
|
||||||
## Logic breakdown of a simple game
|
## Logic breakdown of a simple game
|
||||||
|
|
||||||
TODO hangman exercise
|
```
|
||||||
|
***********************
|
||||||
|
* welcome to hangman! *
|
||||||
|
***********************
|
||||||
|
|
||||||
|
guess the hidden word below
|
||||||
|
---------------------------
|
||||||
|
word: *****
|
||||||
|
guess a letter: a
|
||||||
|
word: a****
|
||||||
|
guess a letter: l
|
||||||
|
word: a**l*
|
||||||
|
guess a letter: p
|
||||||
|
word: appl*
|
||||||
|
guess a letter: e
|
||||||
|
word: apple
|
||||||
|
*****************
|
||||||
|
* you found it! *
|
||||||
|
*****************
|
||||||
|
do you want to play a new game? (Y/N)
|
||||||
|
```
|
||||||
|
|
||||||
## Trivial pursuit multiple choice game
|
## Trivial pursuit multiple choice game
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue