Python Extension Proposal
https://www.python.org/dev/peps/
xBeautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.
xReadability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.
xThere should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.Now is better than never.Although never is often better than *right* now.
xIf the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea-- let's do more of those!
Écrivons un peu de python dans un fichier code.py.
xxxxxxxxxxdef MySum(x,x): return x+yprint(MySum(1,2)) xxxxxxxxxx$ python code.py File "code.py", line 4 def MySum(x,x): ^SyntaxError: duplicate argument 'x' in function definitionxxxxxxxxxxFlake8: Your Tool For Style Guide Enforcement
xxxxxxxxxx$ pip install flake8xxxxxxxxxxSimple Python style checker in one Python file
xxxxxxxxxxA simple program which checks Python source files for errors
xxxxxxxxxxPython code complexity micro-tool
xxxxxxxxxx$ flake8 code.pycode.py:1:1: F831 duplicate argument 'x' in function definitioncode.py:2:14: F821 undefined name 'y' xxxxxxxxxxdef MySum(x,x): return x+yprint(MySum(1,2)) xxxxxxxxxx$ flake8 code.pycode.py:1:1: F831 duplicate argument 'x' in function definitioncode.py:1:13: E231 missing whitespace after ','code.py:2:14: F821 undefined name 'y'code.py:3:1: E305 expected 2 blank lines after class or function definition, found 0code.py:3:14: E231 missing whitespace after ','
xAs PEP 20 says, “Readability counts”.A style guide is about consistency.Consistency with this style guide is important.Consistency within a project is more important.Consistency within one module or function is the most important.
xxxxxxxxxxHowever, know when to be inconsistent.Sometimes style guide recommendations just aren't applicable.When in doubt, use your best judgment.Look at other examples and decide what looks best.And don’t hesitate to ask!
Code layout
Comments
Naming Conventions
Overriding Principle
Descriptive: Naming Styles
Prescriptive: Naming Conventions
Public and internal interfaces
Programming Recommendations
xxxxxxxxxx$ flake8 code.pycode.py:1:1: F831 duplicate argument 'x' in function definitioncode.py:1:13: E231 missing whitespace after ','code.py:2:14: F821 undefined name 'y'code.py:3:1: E305 expected 2 blank lines after classor function definition, found 0code.py:3:14: E231 missing whitespace after ',' xxxxxxxxxxdef MySum(x,x): return x+yprint(MySum(1,2)) xxxxxxxxxxdef MySum(x, y): return x+yprint(MySum(1, 2))xxxxxxxxxxExtension for flake8 which uses pydocstyle to check docstrings
xxxxxxxxxxA static analysis tool for checking compliance with Python docstring conventions.Supports most of PEP 257 out of the box, but it should not be considered a reference implementation.
xxxxxxxxxxThe aim of this PEP is to standardize the high-level structure of docstrings:what they should contain, and how to say it (without touching on any markup syntax within docstrings).The PEP contains conventions, not laws or syntax.
A universal convention supplies all of maintainability, clarity,consistency, and a foundation for good programming habits too.What it doesn't do is insist that you follow it against your will.That's Python!"
—Tim Peters on comp.lang.python, 2001-06-16
xxxxxxxxxx$ pip install flake8-docstrings xxxxxxxxxx$ flake8 code.pycode.py:1:1: D100 Missing docstring in public modulecode.py:1:1: D103 Missing docstring in public function xxxxxxxxxx'a simple script to add two numbers'def MySum(x, y): 'add x and y' return x+yprint(MySum(1, 2)) xxxxxxxxxx$ flake8 code.pycode.py:1:1: D300 Use """triple double quotes"""code.py:1:1: D400 First line should end with a periodcode.py:2:1: E302 expected 2 blank lines, found 0code.py:2:1: D300 Use """triple double quotes"""code.py:2:1: D400 First line should end with a periodcode.py:2:1: D403 First word of the first line should be properly capitalized xxxxxxxxxx"""A simple script to add two numbers."""def MySum(x, y): """We add x and y.""" return x+yprint(MySum(1, 2))xxxxxxxxxxPylint is a tool that checks for errors in Python code, tries to enforce a coding standard and looks for code smells.It can also look for certain type errors, it can recommend suggestions about how particular blocks can be refactored and can offer you details about the code's complexity.
xxxxxxxxxx$ pip install pylint xxxxxxxxxx$ pylint code.pyNo config file found, using default configuration************* Module codeC: 4, 0: Function name "MySum" doesn't conform to snake_case naming style (invalid-name)C: 4, 0: Argument name "x" doesn't conform to snake_case naming style (invalid-name)C: 4, 0: Argument name "y" doesn't conform to snake_case naming style (invalid-name)-------------------------------------------------------------Your code has been rated at 0.00/10 xxxxxxxxxx"""a simple script to add two numbers."""def my_sum(first, second): """We add first and second.""" return first+secondprint(my_sum(1, 2))Parameter documentation checker
If you document the parameters of your functions, methods and constructors and their types systematically in your code this optional component might be useful for you. Sphinx style, Google style, and Numpy style are supported.
:param first: The first number to add :type first: int :param second: The second number to add :type second: int :returns: The result of the computation of first and second :rtype: int
Args:
first (int): The first number to add
second (int): The second number to add
Returns:
int: The result of the computation of first and second
Parameters
----------
first: int
The first number to add
second: int
The second number to add
Returns
-------
int
The result of the computation of first and second
xxxxxxxxxx$ pylint --generate-rcfile > .pylintrcx[MASTER]load-plugins=pylint.extensions.docparams[DESIGN]accept-no-param-doc=no
xxxxxxxxxx$ pylint code.pyUsing config file .pylintrc************* Module codeW: 4, 0: "first, second" missing in parameter documentation (missing-param-doc)W: 4, 0: "first, second" missing in parameter type documentation (missing-type-doc)--------------------------------------------------------------Your code has been rated at 3.33/10 xxxxxxxxxx"""a simple script to add two numbers."""def my_sum(first, second): """We add first and second. Parameters ---------- first: int The first number to add second: int The second number to add Returns ------- int The result of the computation of first and second """ return first+secondprint(my_sum(1, 2)) xxxxxxxxxx$ flake8 code.pycode.py:4:1: D413 Missing blank line after last section xxxxxxxxxx"""a simple script to add two numbers."""def my_sum(first, second): """We add first and second. Parameters ---------- first: int The first number to add second: int The second number to add Returns ------- int The result of the computation of first and second """ return first+secondprint(my_sum(1, 2))Pour
xxxxxxxxxxdef MySum(x,y): return x+yprint(MySum(1,2))A tool that automatically formats Python code to conform to the PEP 8 style guide.
It uses the pycodestyle utility to determine what parts of the code needs to be formatted. autopep8 is capable of fixing most of the formatting issues that can be reported by pycodestyle.
xxxxxxxxxx$ pip install autopep8 xxxxxxxxxx$ autopep8 code.py > code2.py xxxxxxxxxxdef MySum(x, y): return x+yprint(MySum(1, 2))Yet another Python formatter
A formatter for Python files
The ultimate goal is that the code YAPF produces is as good as the code that a programmer would write if they were following the style guide.
xxxxxxxxxx$ pip install yapf xxxxxxxxxx$ yapf code.py > code2.py xxxxxxxxxxdef MySum(x, y): return x + yprint(MySum(1, 2))The uncompromising Python code formatter
xxxxxxxxxxBy using it, you agree to cede control over minutiae of hand-formatting.In return, Black gives you speed, determinism, and freedom from pycodestyle nagging about formatting. You will save time and mental energy for more important matters.
xxxxxxxxxx$ pip install black xxxxxxxxxx$ black code.pyreformatted code.pyAll done! ✨ 🍰 ✨1 file reformatted. xxxxxxxxxxdef MySum(x, y): return x + yprint(MySum(1, 2)) xxxxxxxxxxl = [1, 2, 3,] xxxxxxxxxxl = [1, 2, 3] xxxxxxxxxxTracebackException.from_exception(exc, limit, lookup_lines, capture_locals) xxxxxxxxxxTracebackException.from_exception( exc, limit, lookup_lines, capture_locals) xxxxxxxxxxdef very_important_function( template: str, *variables, file: os.PathLike, debug: bool = False): """Applies `variables` to the `template` and writes to `file`.""" with open(file, 'w') as f: ... xxxxxxxxxxdef very_important_function( template: str, *variables, file: os.PathLike, debug: bool = False,): """Applies `variables` to the `template` and writes to `file`.""" with open(file, "w") as f: ...Rien.
Nada.
Que tchi.
xxxxxxxxxxdef MySum(x, y): """ Parameters ---------- x : y : Returns ------- """ return x + yprint(MySum(1, 2))Sort your python imports for you so you don't have to.
xxxxxxxxxx$ pip install isort xxxxxxxxxxfrom my_lib import Objectprint("Hey")import osfrom my_lib import Object3from my_lib import Object2import sysfrom third_party import lib15, lib1, lib2, lib3, lib4, lib5, lib6, lib7, lib8, lib9, lib10, lib11, lib12, lib13, lib14import sysfrom __future__ import absolute_importfrom third_party import lib3print("yo") xxxxxxxxxxfrom __future__ import absolute_importimport osimport sysfrom third_party import (lib1, lib2, lib3, lib4, lib5, lib6, lib7, lib8, lib9, lib10, lib11, lib12, lib13, lib14, lib15)from my_lib import Object, Object2, Object3print("Hey")print("yo")This PEP introduces a syntax for adding arbitrary metadata annotations to Python functions.
xxxxxxxxxxdef haul(item: Haulable, *vargs: PackAnimal) -> Distance: ... xxxxxxxxxxdef compile(source: "something compilable", filename: "where the compilable thing comes from", mode: "is this a single statement or a suite?"): ...[...]the community would benefit from a standard vocabulary and baseline tools within the standard library. This PEP introduces a provisional module to provide these standard definitions and tools, along with some conventions for situations where annotations are not available.
xxxxxxxxxxdef greeting(name: str) -> str: return 'Hello ' + namemsg = greeting('John') # type: strThis PEP aims at adding syntax to Python for annotating the types of variables.
xxxxxxxxxxmsg: str = greeting('John')
Python will remain a dynamically typed language, and the authors have no desire to ever make type hints mandatory, even by convention.
Python restera un langage dynamiquement typé, et les auteurs n'ont aucun désir de obligatoires les indications de type, jamais, même par convention.
xxxxxxxxxxdef MySum(x: str, y: list) -> float: return x + yprint(MySum(1, 2)) xxxxxxxxxx$ python code.py3Optional Static Typing for Python
xxxxxxxxxxMypy is an experimental optional static type checker for Python that aims to combine the benefits of dynamic (or "duck") typing and static typing.Mypy combines the expressive power and convenience of Python with a powerful type system and compile-time type checking.
xxxxxxxxxx$ pip install mypy xxxxxxxxxxdef MySum(x: str, y: list) -> float: return x + yprint(MySum(1, 2)) xxxxxxxxxx$ mypy code.pycode.py:2: error: Incompatible return value type (got "str", expected "float")code.py:2: error: Unsupported operand types for + ("str" and "List[Any]")code.py:5: error: Argument 1 to "MySum" has incompatible type "int"; expected "str"code.py:5: error: Argument 2 to "MySum" has incompatible type "int"; expected "List[Any]" xxxxxxxxxxdef MySum(x: int, y: int) -> int: return x + yprint(MySum(1, "foo8")) xxxxxxxxxx$ mypy code.pycode.py:5: error: Argument 2 to "MySum" has incompatible type "str"; expected "int"A performant type-checker for Python 3
We believe statically typing what are essentially fully dynamic languages gives our code stability and improves developer productivity.
xxxxxxxxxx$ pip install pyre-check xxxxxxxxxxdef MySum(x: str, y: list) -> float: return x + yprint(MySum(1, 2)) xxxxxxxxxx$ pyre check ƛ Found 2 type errors!code.py:2:4 Incompatible return type [7]: Expected `float` but got `str`.code.py:2:19 Incompatible parameter type [6]: Expected `str` but got `typing.List[typing.Any]`.Auto-generate PEP-484 annotations
A system for Python that generates static type annotations by collecting runtime types
xxxxxxxxxxdef MySum(x,x): return x+yprint(MySum(1,2)) xxxxxxxxxx"""a simple script to add two numbers."""def my_sum(first, second): """We add first and second. Parameters ---------- first: int The first number to add second: int The second number to add Returns ------- int The result of the computation of first and second """ return first+secondprint(my_sum(1, 2)Configuration éditeur / IDE
docstrings
analyse de code
ré-écriture automatique
Coder
Lancer les checks avant chaque commit (ou via commithook)
lint
tests
Si OK
push
pull/merge-request...
Revue de code
ENJOY. Adieu:
Vous et votre équipe me remercierez à la prochaine conf ;)
mixt: https://github.com/twidi/mixt/
Take back control of your Github issues, pull requests, and notifications
Les slides seront publiés sur https://twidi.github.io/