Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cc4dfe3
commit 6f670a7
Showing
5 changed files
with
276 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,123 @@ | ||
# TP3 - Orienté Objet | ||
|
||
TODO | ||
## Exercices 1 | ||
|
||
Utiliser [person.py](./person.py). | ||
|
||
#### 1.1 Ajouter des attributs | ||
|
||
Rajouter les attributs `email` et `phone` à la classe `Person` et ajouter ce code à `main`: | ||
```py | ||
print(f"Email: {john.email}") | ||
print(f"Phone: {john.phone}") | ||
``` | ||
|
||
#### 1.2 Method `__str__` | ||
|
||
Exécuter `print(john)` dans `main` | ||
|
||
```py | ||
def __str__(self) -> str: | ||
return f"{self.first_name} {self.last_name}" | ||
``` | ||
|
||
Exécuter `print(john)` dans `main` à nouveau. | ||
|
||
## Exercice 2 | ||
|
||
Utiliser [person_2.py](./person_2.py). | ||
|
||
Rajouter une ligne au niveau du TODO pour obtenir la sortie suivante : | ||
``` | ||
Is John of age: True | ||
Is Bob of age: True | ||
Change the age of majority to 32 | ||
Is John of age: False | ||
Is Bob of age: True | ||
``` | ||
Cette ligne ne **doit pas utiliser les objets `john` ou `bob`** | ||
|
||
## Exercice 3 | ||
|
||
Utiliser [vectors.py](./vectors.py). | ||
|
||
#### 3.1 Création des classes | ||
|
||
Un vecteur du plan est composé d'un point de départ et d'un point d'arrivé. | ||
Créez une classe `Point` et une classe `Vector` de manière à représenter des points et des vecteurs du plan en Python. | ||
Vérifier que la fonction `main` s'exécute sans erreurs et que les éléments affichés sont mathématiquements corrects. | ||
|
||
|
||
#### 3.2 Produit scalaire | ||
|
||
Ajouter une méthode qui calcule le produit scalaire de deux vecteurs. | ||
|
||
|
||
#### 3.3 Ajouter des méthodes spéciales | ||
|
||
Ajouter la méthode spéciale `__str__` aux deux classes. Résultat attendu : | ||
```sh | ||
print(point_A) # "Point(-2, -1)" | ||
print(vector_AB) # "Vector(5, 8)" | ||
``` | ||
|
||
Ensuite, ajouter les méthodes séciales à la classe `Vector`: | ||
- `__add__` | ||
- `__sub__` | ||
- `__neg__` | ||
- `__mul__` | ||
Vérifier que la fonction `main_2` s'exécute sans erreurs et vérifier que les résultats sont mathématiquement corrects. | ||
|
||
Pour les annotations de types, on pourra utiliser le type `Self` | ||
```py | ||
from typing import Self | ||
``` | ||
|
||
#### 3.4 Constructeur alternatif | ||
|
||
On souhaite pouvoir créer un vecteur en donnant à l'initialisation seulement le point d'arrivé. Dans ce cas, le point de départ sera l'origine. | ||
On souhaite que ce code fonctionne : | ||
```py | ||
vector_OB = Vector.from_origin(point_B) | ||
``` | ||
|
||
En utilisant une **méthode de class**, implémenter la méthode `from_origin` sur la classe `Vector`. | ||
|
||
|
||
## Exercice 4 | ||
|
||
Utiliser [threads.py](./threads.py). | ||
|
||
#### 4.1 Exécuter et comprendre le code | ||
|
||
Jusqu'à présent, les programmes que nous avons écrit s'exécutaient dans un seul thread (le thread principal). Exécuter du code dans un nouveau thread permet d'exécuter ce code **en parallèle**. | ||
Il y a plusieurs manières de créer un thread en Python. Pour ce TP, nous allons nous créer une classe qui **hérite de `threading.Thread`**. `threading.Thread` contient plusieurs méthodes et attributs utiles : | ||
- `my_thread.is_alive()`: renvoie True si le thread est en cours d'exécution, False sinon | ||
- `my_thread.start()`: crée le thread et commence l'exécution du code de la méthode `run` | ||
- `my_thread.run()`: code exécuté dans le thread. | ||
- `my_thread.run()`: code exécuté dans le thread. | ||
- `my_thread.join()`: block l'exécution (attend) jusqu'á ce que `my_thread` ait fini (jusqu'à que ce `my_thread.run` ait fini). | ||
|
||
A noter qu'un thread ne peut être démarré qu'une seule fois ! | ||
|
||
Lisez le code, exécutez-le et comprenez son fonctionnement. Vous pouvez changer les valeurs des `time.sleep` et observer le résultat. | ||
|
||
Resources pour aller plus loin après le TP : | ||
- https://realpython.com/intro-to-python-threading/ | ||
|
||
#### 4.2 Factorisation | ||
|
||
Le code actuel contient plusieurs problèmes : | ||
- "magic values" pour 1s et 3s utilisés dans time.sleep(...) | ||
- "magic values" pour 1 et 3 utilisés dans for i in range(...) | ||
- duplications de code : les deux classes sont quasi identiques | ||
|
||
Factorisez ces deux classes en une seule pour enlever la duplication de code. Pour éviter d'hardcoder les valeurs cités plus haut, passez-les en paramètre de l'initialiseur. | ||
Exemple de code main: | ||
```py | ||
counter1_thread = Counter(stop_value=10, sleep_delay_s=1) # count from 0 to 10 with 1s delay | ||
counter2_thread = Counter(50, 3) # count from 0 to 50 with 3s delay | ||
counter3_thread = Counter(20) # count from 0 to 20 with 1s delay (1s is the default) | ||
``` | ||
|
||
Vous devrez pour cela *overrider* la méthode `__init__`. Pensez à appeler `super()__init__()`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
"""Representation of a person.""" | ||
|
||
|
||
class Person: | ||
def __init__(self, first_name: str, last_name: str, age: int) -> None: | ||
self.first_name = first_name.capitalize() | ||
self.last_name = last_name.upper() | ||
self.age = age | ||
|
||
|
||
def main(): | ||
john = Person("John", "Doe", 30) | ||
print(f"First name: {john.first_name}") | ||
print(f"Last name: {john.last_name}") | ||
print(f"Age: {john.age}") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
"""Representation of a person.""" | ||
|
||
|
||
class Person: | ||
|
||
AGE_MAJORITY = 18 | ||
|
||
def __init__(self, first_name: str, last_name: str, age: int) -> None: | ||
self.first_name = first_name.capitalize() | ||
self.last_name = last_name.upper() | ||
self.age = age | ||
|
||
def is_of_age(self) -> bool: | ||
"""Return if the person is over the age of majority or not.""" | ||
return self.age >= self.AGE_MAJORITY | ||
|
||
|
||
def main(): | ||
john = Person("John", "Doe", 30) | ||
bob = Person("Bob", "Smith", 34) | ||
|
||
print(f"Is John of age: {john.is_of_age()}") | ||
print(f"Is Bob of age: {bob.is_of_age()}") | ||
|
||
print("Change the age of majority to 32") | ||
# TODO | ||
|
||
print(f"Is John of age: {john.is_of_age()}") | ||
print(f"Is Bob of age: {bob.is_of_age()}") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"""Training with threads.""" | ||
|
||
import time | ||
from threading import Thread | ||
|
||
|
||
class Counter1(Thread): | ||
"""Thread counting with 1s delay.""" | ||
|
||
def start(self) -> None: | ||
super().start() | ||
print("Start counting: delay = 1s") | ||
|
||
def run(self) -> None: | ||
for i in range(10): | ||
print(f"Counter 1: {i}") | ||
time.sleep(1) | ||
|
||
|
||
class Counter3(Thread): | ||
"""Thread counting with 3s delay.""" | ||
|
||
def start(self) -> None: | ||
super().start() | ||
print("Start counting: delay = 3s") | ||
|
||
def run(self) -> None: | ||
for i in range(3): | ||
print(f"Counter 3: {i}") | ||
time.sleep(3) | ||
|
||
|
||
def main(): | ||
counter1_thread = Counter1() | ||
counter3_thread = Counter3() | ||
print(f"{counter1_thread.is_alive() = }") | ||
|
||
# Start both threads: both code will run in parallel | ||
counter1_thread.start() | ||
counter3_thread.start() | ||
print(f"{counter1_thread.is_alive() = }") | ||
|
||
print("Main thread: sleeping") | ||
time.sleep(12) | ||
|
||
# Make sure each thread has finished, or wait until they are finished | ||
print("Main thread: waiting for all threads") | ||
counter1_thread.join() | ||
counter3_thread.join() | ||
print(f"{counter1_thread.is_alive() = }") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
"""Manipulation of 2D-vectors.""" | ||
|
||
from __future__ import annotations | ||
|
||
|
||
def main(): | ||
origin = Point(0, 0) | ||
point_A = Point(-2, -1) | ||
point_B = Point(3, 7) | ||
|
||
print(f"Point O: x={origin.x} y={origin.y}") | ||
print(f"Point A: x={point_A.x} y={point_A.y}") | ||
|
||
vector_OA = Vector(origin, point_A) | ||
vector_AB = Vector(point_A, point_B) | ||
|
||
print(f"Vector OA: dx={vector_OA.x} dy={vector_OA.y}") | ||
print(f"Vector AB: dx={vector_AB.x} dy={vector_AB.y}") | ||
|
||
|
||
def main_2(): | ||
v = Vector(1, 2) | ||
v2 = Vector(1, 0) | ||
print(v.dot_prod(v2)) | ||
print(v2.dot_prod(v)) | ||
|
||
|
||
def main_3(): | ||
v = Vector(1, 2) | ||
v2 = Vector(1, 0) | ||
print(-v) | ||
print(-(-v)) | ||
print(v + v2) | ||
print(v - v2) | ||
print(v * 3) | ||
print(v2 * -10) | ||
|
||
|
||
def main_4(): | ||
point_B = Point(3, 7) | ||
vector_OB = Vector.from_origin(point_B) | ||
print(vector_OB) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() | ||
# main_2() | ||
# main_3() | ||
# main_4() |