diff --git a/README.md b/README.md
index facc0052955c800a3c4006edba9162a979bc0fc4..20ebf6e1f3e1eb42398920ce9dfab4226dbaec0f 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ This is not a formation to learn python from scratch, you should know the python
 
 # Why python ?
 
-## Pro
+## Pros
 
  - flexibility (not typed)
  - concision of the syntax
diff --git a/e_good_practices/README.md b/e_good_practices/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..00dbf69cd77e9a91bbcaf02584adee58fdf86a0e
--- /dev/null
+++ b/e_good_practices/README.md
@@ -0,0 +1,230 @@
+
+# Good practices in python
+
+The list below is inspired from [https://docs.quantifiedcode.com/python-anti-patterns/]
+
+## About good practices
+
+The practices below are not enforced by python, your code will run even if you don't respect them.
+
+Here are a few reasons you should use them:
+ - your code will be easier to read;
+ - your code will be easier to write;
+ - your code will be easier to maintain;
+ - you won't surprise others that will read your code;
+ 
+It will save time for everybody, you included !
+
+## Naming conventions
+
+Details:
+  - [https://docs.quantifiedcode.com/python-anti-patterns/maintainability/using_single_letter_as_variable_name.html]
+  - [https://docs.quantifiedcode.com/python-anti-patterns/correctness/assigning_to_builtin.html]
+  - [https://docs.quantifiedcode.com/python-anti-patterns/readability/putting_type_information_in_a_variable_name.html]
+  - [https://docs.quantifiedcode.com/python-anti-patterns/readability/using_camelcase_in_function_names.html]
+
+
+Conventions
+ - variables / functions: snake_case
+ - classes: CamelCase
+ 
+```python
+path_to_images = ...
+
+def get_path_to_images():
+    pass
+    
+class PathToImages:
+    pass
+```
+
+**/!\ Do not use built-in function names to store variables**
+
+
+```python
+# You shouldn't do
+max = 10
+min = 0
+```
+
+**Don't use single letter as names**
+
+
+## Use comprehensions 
+
+See [../a_list_comprehension]
+
+Details
+ - [https://docs.quantifiedcode.com/python-anti-patterns/readability/using_map_or_filter_where_list_comprehension_is_possible.html]
+ - [https://docs.quantifiedcode.com/python-anti-patterns/readability/not_using_a_dict_comprehension.html]
+  
+
+## Encapsulation
+
+Details
+ - [https://docs.quantifiedcode.com/python-anti-patterns/correctness/accessing_a_protected_member_from_outside_the_class.html]
+ - [https://docs.quantifiedcode.com/python-anti-patterns/correctness/implementing_java-style_getters_and_setters.html]
+
+Python breaks the POO rule of encapsulation.
+
+Nonetheless, there are two things you can still do to protect your classes' integrity.
+
+### Use the _ naming convention
+
+If you start an attribute/method name by an underscore, it means that it shouldn't be accessed from outside the object.
+
+### Anti-pattern
+
+Don't use setters/getters !
+
+```python
+class Person:
+    def __init__(self, age):
+        self._age = age
+        
+    def get_age(self):
+        return self._age
+        
+    def set_age(self, age):
+        self._age = age
+```
+
+### Good Practice
+
+The attribute should be public:
+```python
+class Person:
+    def __init__(self, age):
+        self.age = age
+```
+ 
+### To use carefully
+ 
+If you really need to have a setter (to change another variable, ...), you can (but only if you really need it) use the [@property decorator](https://docs.python.org/3/library/functions.html#property).
+
+## Mutable value as default argument
+
+Details
+ - [https://docs.quantifiedcode.com/python-anti-patterns/correctness/mutable_default_value_as_argument.html]
+
+See [../d_dataclassses/00_mutable.py] for examples.
+
+### Anti pattern
+
+```python
+class BadStock:
+    def __init__(self, products: List[str] = []):
+        self.products: List[str] = products
+
+    def add_to_stock(self, product: str):
+        self.products.append(product)
+```
+
+Every BadStock instance will share the same `products` attribute !
+
+### Good practice
+
+```python
+class GoodStock:
+    def __init__(self, products: List[str] = None):
+        self.products: List[str] = products or []
+
+    def add_to_stock(self, product: str):
+        self.products.append(product)
+```
+
+This way, the default list is created during the object instantiation, so it will be a different one for each object.
+
+NB: If you use dataclasses, the `default_factory` function will take care of this issue for you.
+
+
+## Functions that return more than one type
+
+Details
+ - [https://docs.quantifiedcode.com/python-anti-patterns/maintainability/returning_more_than_one_variable_type_from_function_call.html]
+
+If your function return different types according to the situation, it makes it more difficult to use. It should be avoided. 
+
+### Anti-pattern
+
+```python
+def get_last_subscriber(subscribers):
+    if not len(subscribers):
+        return None
+        
+    return subscribers[-1]
+    
+    
+def do_something_to_last_subscriber(subscribers):
+    last_subscriber = get_last_subscriber(subscribers)
+    
+    if last_subscriber is None:
+        # No subscriber, do something
+        pass
+    else:
+        # Subscribers, do something else
+        pass
+```
+
+### Good practice
+
+```python
+class NoSubscribersException(Exception):
+    pass
+    
+    
+def get_last_subscriber(subscribers):
+    if not len(subscribers):
+        raise NoSubscribersException()
+        
+    return subscribers[-1]
+    
+    
+def do_something_to_last_subscriber(subscribers):
+    try:
+        last_subscriber = get_last_subscriber(subscribers)
+        # Subscribers, do something
+        pass
+    except NoSubscribersException:
+        # No subscriber, do something
+        pass
+```
+
+
+## Unpythonic loops
+
+Details
+ - [https://docs.quantifiedcode.com/python-anti-patterns/readability/using_an_unpythonic_loop.html]
+ - [https://docs.quantifiedcode.com/python-anti-patterns/readability/not_using_zip_to_iterate_over_a_pair_of_lists.html]
+ 
+You should use [enumerate](https://docs.python.org/3/library/functions.html#enumerate), [zip](https://docs.python.org/3/library/functions.html#zip), when appropriate.
+ 
+### Anti-pattern
+
+```python
+persons = ['Jean', 'Paul', 'Fred']
+
+for i in range(len(persons)):
+    person = persons[i]
+    print(f'the {i+1}th person in the list is {person}')
+``` 
+
+Or, worse:
+
+```python
+persons = ['Jean', 'Paul', 'Fred']
+i = 0
+
+for person in persons:
+    i += 1
+    print(f'the {i+1}th person in the list is {person}')
+``` 
+
+### Good practice
+
+```python
+persons = ['Jean', 'Paul', 'Fred']
+
+for i, person in enumerate(persons):
+    print(f'the {i+1}th person in the list is {person}')
+```