diff --git a/assets/plan.FCStd b/assets/plan.FCStd new file mode 100644 index 0000000..f4863f3 Binary files /dev/null and b/assets/plan.FCStd differ diff --git a/assets/plan.FCStd1 b/assets/plan.FCStd1 new file mode 100644 index 0000000..8bb9fb7 Binary files /dev/null and b/assets/plan.FCStd1 differ diff --git a/assets/plan_3d.png b/assets/plan_3d.png new file mode 100644 index 0000000..7f133b0 Binary files /dev/null and b/assets/plan_3d.png differ diff --git a/assets/plan_topview.png b/assets/plan_topview.png new file mode 100644 index 0000000..8a50e51 Binary files /dev/null and b/assets/plan_topview.png differ diff --git a/learning_python3.md b/learning_python3.md index 7109132..6c9c821 100644 --- a/learning_python3.md +++ b/learning_python3.md @@ -41,8 +41,7 @@ The quote above is taken shamelessly from [wikipedia](https://en.wikipedia.org/w ### Writing code -Scripts are text files, plain and simple. -So in order to **write** a Python3 script all we need is a text editor. +Scripts are text files, plain and simple. So in order to **write** a Python3 script all we need is a text editor. Nano, vim, notepad++ all do a good job of editing plain text files but some make it *easier* than others. You've noticed that vim colors the code of a shell script no? One of the many features of an [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment) is *syntax highlighting*. @@ -1825,6 +1824,7 @@ We already saw a dictionaries which are good mapping structures but how can we s 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. +**TODO CSV** # Now for some useful scripting @@ -1836,13 +1836,216 @@ Don't hesitate to ask for help! # Creating our own objects +We've been using built-in objects like `str`, `int` and `float` but we can create our own objects as well! +You might wonder *why* you would do this and that's a valid reflection. +For beginners it's often a bit unclear when to create your own objects and when not. +We'll go over some abstract examples to showcase the syntax and usage, then do a couple of practical exercises. + ## First some *abstract* examples -TODO simple animal or vehicle exercise +A basic abstraction can be seen below. +The main thing to take away from this code block is the new [keyword](https://docs.python.org/3/reference/compound_stmts.html#class-definitions) `class`. +Once the new `class` is defined, we can create an **instance** of this class. +We can create as many instances as we want, just as with `str`! + +```python +class Animal(object): + pass + + +dog = Animal() +dog.name = "bobby" +dog.legs = 4 + +print("the {} named {} has {} legs".format( + dog.__class__.__name__, + dog.name, + dog.legs, + ) +) +``` + +We can create as many attributes as we want and in the example above we do this for a `name` and a number of `legs`. +An `Animal` will *always* have a `name` and a number of `legs` so why don't we foresee their existence? +We can do this as follows. + +```python +class Animal(object): + def __init__(self, name, legs): + self.name = name + self.legs = legs + + +dog_1 = Animal("bobby", 4) +dog_2 = Animal("dianne", 4) +dog_3 = Animal("rex", 3) + +all_my_dogs = [dog_1, dog_2, dog_3] + +for dog in all_my_dogs: + print("the {} named {} has {} legs".format( + dog.__class__.__name__, + dog.name, + dog.legs, + ) + ) +``` + +Now, objects don't just possess *attributes*, they can also *do* things! +Executing a piece of code should get you thinking about **functions**. +A function belonging to a `class` is called a **method** and we can easily create them! + +```python +class Animal(object): + def __init__(self, name, legs): + self.name = name + self.legs = legs + + def speaks(self): + print("barks ~~{}~~!".format(self.name.upper())) + + +dog_1 = Animal("bobby", 4) +dog_2 = Animal("dianne", 4) +dog_3 = Animal("rex", 3) + +all_my_dogs = [dog_1, dog_2, dog_3] + +for dog in all_my_dogs: + print("the {} named {} has {} legs".format( + dog.__class__.__name__, + dog.name, + dog.legs, + ) + ) + dog.speaks() +``` + +And just as with functions defined outside of a `class` we can add arguments to our own methods. + +```python +class Animal(object): + def __init__(self, name, legs, owner): + self.name = name + self.legs = legs + self.owner = owner + + def speaks(self): + print("barks ~~{}~~!".format(self.name.upper())) + + def jumps_on(self, person): + if person == self.owner: + print("{} licks {}'s face...".format(self.name, person)) + else: + print("{} growls in {}'s face".format(self.name, person)) + +dog_1 = Animal("bobby", 4, "dave") +dog_2 = Animal("dianne", 4, "alice") +dog_3 = Animal("rex", 3, "dave") + +all_my_dogs = [dog_1, dog_2, dog_3] + +for dog in all_my_dogs: + print("the {} named {} has {} legs".format( + dog.__class__.__name__, + dog.name, + dog.legs, + ) + ) + dog.speaks() + dog.jumps_on("alice") + print("\t---\n") +``` + +🏃 Try it +--- + +Think of some other world objects you can create a class for and do so. +The first one that comes to mind is vehicles but you can do anything that makes sense to you. ## Class inheritance -TODO shapes and surfaces +Inheritance is one of the four main pillars of Object Orientated Programming. +The idea is pretty simple, classes can inherit behaviour from a *parent* class. +For example, `Dog` and `Cat` are both `Animal` so they share common attributes and methods. + +```python +class Animal(object): + def __init__(self, name, legs, owner): + self.name = name + self.legs = legs + self.owner = owner + + def jumps_on(self, person): + if person == self.owner: + print("{} licks {}'s face...".format(self.name, person)) + else: + print("{} growls in {}'s face".format(self.name, person)) + + +class Dog(Animal): + CALL = "barks" + + def __init__(self, name, legs=4, owner=None): + Animal.__init__(self, name, legs, owner) + + def speaks(self): + print("{} ~~{}~~!".format(self.__class__.CALL, self.name.upper())) + + +class Cat(Animal): + CALL = "miauws" + + def __init__(self, name, legs=4, owner=None): + Animal.__init__(self, name, legs, owner) + + def speaks(self): + print("{} ~~{}~~!".format(self.__class__.CALL, self.name.lower())) + + +class Parrot(Animal): + CALL = "creaks" + + def __init__(self, name, legs=2, owner=None): + Animal.__init__(self, name, legs, owner) + + def speaks(self): + print("{} ~~{}~~!".format(self.__class__.CALL, self.name.lower())) + + def jumps_on(self, person): + print("you're silly, I'm a {}, I don't jump...".format( + self.__class__.__name__) + ) + + +animal_1 = Dog(name="bobby", owner="dave") +animal_2 = Dog(name="dianne", owner="alice") +animal_3 = Cat("garfield", 3, "dave") +animal_4 = Parrot("coco", "alice") +animal_5 = Cat("gertrude", 3, "dave") + +all_animals = [animal_1, animal_2, animal_3, animal_4, animal_5] + +for animal in all_animals: + print("the {} named {} has {} legs".format( + animal.__class__.__name__, + animal.name, + animal.legs, + ) + ) + animal.speaks() + animal.jumps_on("alice") + print("\t---\n") +``` + +🏃 Try it +--- + +Take the additional class yyou made, such as vehicle and do some inheritance. +For vehicles you could create a base class with a brand and number of wheels and seats. +Then inherit for a bus, bike, car, cycle, etc. + +**TODO shapes and surfaces** ## Now some *practical* improvements @@ -1905,6 +2108,3 @@ TODO add a countdown timer to the multiple choice game # Coding challenge - Login generator with GUI # Coding challenge - Trivial pursuit with GUI - -# Introduction to the `logging` library -