| @@ -40,7 +40,10 @@ name = "John" | |||||
| print("Bonjour %s!" % name) # 's' comme string | print("Bonjour %s!" % name) # 's' comme string | ||||
| age = 42 | age = 42 | ||||
| print("Vous avez %i ans" % 42) # 'i' comme integer | |||||
| print("Vous avez %i ans" % age) # 'i' comme integer | |||||
| poids = 68.5 | |||||
| print("Vous pesez %f kilos" % poids) # 'f' comme integer | |||||
| ``` | ``` | ||||
| @@ -105,7 +108,7 @@ template.format(reponse, name) | |||||
| * La meilleure de toutes :) | * La meilleure de toutes :) | ||||
| * Plus succint que `format()` | * Plus succint que `format()` | ||||
| * Plus performant que `%` et `.format()` | * Plus performant que `%` et `.format()` | ||||
| * Mais pas avant Python 3.6 | |||||
| * Mais pas avant Python 3.6 (2016) | |||||
| # Principe | # Principe | ||||
| @@ -122,7 +125,9 @@ text = f"Bonjour {name}. Votre score est: {score}" | |||||
| Mais aussi: | Mais aussi: | ||||
| ```python | ```python | ||||
| text = f"2 + 2 égale { 2 + 2 }" | |||||
| a = 2 | |||||
| b = 3 | |||||
| text = f"résultat: {a + b}" | |||||
| ``` | ``` | ||||
| # Conclusion | # Conclusion | ||||
| @@ -141,12 +146,19 @@ Mais si vous avez le choix, utilisez des `f-strings`! | |||||
| ```python | ```python | ||||
| >>> pi = 3.14159265359 | >>> pi = 3.14159265359 | ||||
| >>> truncated = "%.2f" % pi | |||||
| 3.14 | |||||
| >>> f"pi vaut à peu près {pi:.2f}" | |||||
| pi vaut à peu près 3.14 | |||||
| ``` | ``` | ||||
| Le texte dans les accolades après le `:` est un mini-langage de spécification de format. | Le texte dans les accolades après le `:` est un mini-langage de spécification de format. | ||||
| `.2` veut dire: 2 chiffres après la virgule maximum. | |||||
| `.2f` veut dire: 2 chiffres après la virgule maximum. | |||||
| Fonctionne aussi avec `.format()` `et %`: | |||||
| ```python | |||||
| "pi vaut à peu près {:.2f}".format(pi) | |||||
| "pi vaut à peu près %.2f" % pi | |||||
| ``` | |||||
| # Alignements et paddings | # Alignements et paddings | ||||
| @@ -273,19 +285,19 @@ class B(A): | |||||
| ```python | ```python | ||||
| class A: | class A: | ||||
| def method(self): | |||||
| def do_stuff(self): | |||||
| print("A!") | print("A!") | ||||
| class B(A): | class B(A): | ||||
| def method(self): | |||||
| def do_stuff(self): | |||||
| print("B!") | print("B!") | ||||
| >>> a = A() | >>> a = A() | ||||
| >>> a.method() # ok | |||||
| >>> a.do_stuff() # ok | |||||
| 'A!' | 'A!' | ||||
| >>> b = B() | >>> b = B() | ||||
| >>> b.method() | |||||
| >>> b.do_stuff() | |||||
| 'B!' | 'B!' | ||||
| ``` | ``` | ||||
| @@ -294,19 +306,19 @@ class B(A): | |||||
| ```python | ```python | ||||
| class A: | class A: | ||||
| def method(self): | |||||
| def do_stuff(self): | |||||
| print("A!") | print("A!") | ||||
| class B(A): | class B(A): | ||||
| def method(self): | |||||
| super().method() | |||||
| def do_stuff(self): | |||||
| super().do_stuff() | |||||
| print("B!") | print("B!") | ||||
| >>> a = A() | >>> a = A() | ||||
| >>> a.method() # ok | |||||
| >>> a.do_stuff() # ok | |||||
| 'A!' | 'A!' | ||||
| >>> b = B() | >>> b = B() | ||||
| >>> b.method() | |||||
| >>> b.do_stuff() | |||||
| 'A!' | 'A!' | ||||
| 'B!' | 'B!' | ||||
| ``` | ``` | ||||
| @@ -329,7 +341,7 @@ class Pet(Animal): | |||||
| # All dogs are pets | # All dogs are pets | ||||
| class Dog(Pet): | class Dog(Pet): | ||||
| def __init__(self, name): | def __init__(self, name): | ||||
| super().init("dog", name) | |||||
| super().init("dog", name) | |||||
| ``` | ``` | ||||
| # | # | ||||
| @@ -391,7 +403,7 @@ Dans `play` on appelle `self.marvel_client.get_all_characters()` donc la méthod | |||||
| `get_all_characters()` doit: | `get_all_characters()` doit: | ||||
| * exister | * exister | ||||
| * ne prendre aucun agrument | |||||
| * ne prendre aucun argument | |||||
| * retourner une liste de noms | * retourner une liste de noms | ||||
| # Contrats implicites - 2 | # Contrats implicites - 2 | ||||
| @@ -465,10 +477,6 @@ class BaseClient(metaclass=abc.ABCMeta): | |||||
| @abc.abstractmethod | @abc.abstractmethod | ||||
| def get_description(self, name): | def get_description(self, name): | ||||
| pass | pass | ||||
| >>> client = BaseClient() | |||||
| ``` | ``` | ||||
| On retrouve le `@` au-dessus des méthodes. | On retrouve le `@` au-dessus des méthodes. | ||||
| @@ -497,21 +505,23 @@ class MarvelClient(BaseClient): | |||||
| ... | ... | ||||
| ``` | ``` | ||||
| À la construction, Python va vérifier que les méthodes abstraites | |||||
| sont bien surchargées. | |||||
| # Conclusion | |||||
| # Pistes de réflexion | |||||
| Plein de langages ont un concept d'interface. | |||||
| * Que se passe-t-il si on rajoute une méthode dans `BaseClient` sans toucher | |||||
| à `MarvelClient` ni à `FakeClient` ? | |||||
| * Que se passe-t-il si la signature de `get_description()` change? | |||||
| C'est utile de savoir que les interfaces existent en Python et ça peut rendre | |||||
| le code plus clair. | |||||
| # Conclusion | |||||
| Cela dit, dans le cas de Python c'est complètement *optionnel*. | |||||
| Plein de languages ont un concept d'interface. C'est bien utile de savoir, | |||||
| les définir en Python, même si ça ne résout pas tous les problèmes. | |||||
| # | |||||
| \center \huge Atelier | \center \huge Atelier | ||||
| Encore un refactoring | |||||
| # Encore un refactoring | |||||
| # Pour la prochaine fois: | # Pour la prochaine fois: | ||||