Merge branch 'master' into standard-american-english

This commit is contained in:
Marc Poulin
2018-12-20 15:03:09 -07:00
committed by GitHub
17 changed files with 130 additions and 123 deletions
+5 -5
View File
@@ -25,7 +25,7 @@ information. This file is the main entry point for readers of the code.
An :file:`INSTALL` file is less necessary with Python. The installation
instructions are often reduced to one command, such as ``pip install
module`` or ``python setup.py install`` and added to the :file:`README`
module`` or ``python setup.py install``, and added to the :file:`README`
file.
A :file:`LICENSE` file should *always* be present and specify the license
@@ -75,7 +75,7 @@ your source repository so that rebuilding your documentation will
happen automatically.
When run, Sphinx_ will import your code and using Python's introspection
features it will extract all function, method and class signatures. It will
features it will extract all function, method, and class signatures. It will
also extract the accompanying docstrings, and compile it all into well
structured and easily readable documentation for your project.
@@ -215,7 +215,7 @@ more information about a function, what it does, any exceptions it may raise,
what it returns, or relevant details about the parameters.
For more detailed documentation of code a popular style is the one used for the
Numpy project, often called `Numpy style`_ docstrings. While it can take up more
NumPy project, often called `NumPy style`_ docstrings. While it can take up more
lines than the previous example, it allows the developer to include a lot
more information about a method, function, or class. ::
@@ -245,8 +245,8 @@ docstrings, making it easy to incorporate NumPy style docstrings into your
project.
At the end of the day, it doesn't really matter what style is used for writing
docstrings, their purpose is to serve as documentation for anyone who may need
to read or make changes to your code. As long as it is correct, understandable
docstrings; their purpose is to serve as documentation for anyone who may need
to read or make changes to your code. As long as it is correct, understandable,
and gets the relevant points across then it has done the job it was designed to
do.
+1 -1
View File
@@ -205,7 +205,7 @@ will automatically write a bytecode version of that file to disk, e.g.
These ``.pyc`` files should not be checked into your source code repositories.
Theoretically, this behavior is on by default, for performance reasons.
Theoretically, this behavior is on by default for performance reasons.
Without these bytecode files present, Python would re-generate the bytecode
every time the file is loaded.
+3 -3
View File
@@ -19,18 +19,18 @@ In general, these licenses tend to fall into one of two categories:
1. licenses that focus more on the user's freedom to do with the
software as they please (these are the more permissive open
source licenses such as the MIT, BSD, & Apache).
source licenses such as the MIT, BSD, and Apache)
2. licenses that focus more on making sure that the code itself —
including any changes made to it and distributed along with it —
always remains free (these are the less permissive free software
licenses such as the GPL and LGPL).
licenses such as the GPL and LGPL)
The latter are less permissive in the sense that they don't permit
someone to add code to the software and distribute it without also
including the source code for their changes.
To help you choose one for your project, there's a `license chooser <http://choosealicense.com/>`_,
To help you choose one for your project, there's a `license chooser <http://choosealicense.com/>`_;
**use it**.
**More Permissive**
+2 -2
View File
@@ -58,7 +58,7 @@ hierarchy of loggers using dot notation, so using ``__name__`` ensures
no name collisions.
Here is an example of best practice from the `requests source`_ -- place
this in your ``__init__.py``
this in your ``__init__.py``:
.. code-block:: python
@@ -83,7 +83,7 @@ There are at least three ways to configure a logger:
- Using an INI-formatted file:
- **Pro**: possible to update configuration while running using the
function :func:`logging.config.listen` to listen on a socket.
- **Con**: less control (*e.g.* custom subclassed filters or loggers)
- **Con**: less control (e.g. custom subclassed filters or loggers)
than possible when configuring a logger in code.
- Using a dictionary or a JSON-formatted file:
- **Pro**: in addition to updating while running, it is possible to load
+3 -3
View File
@@ -25,7 +25,7 @@ reading. Each one of these projects is a paragon of Python coding.
best intentions in mind.
- `Diamond <https://github.com/python-diamond/Diamond>`_
Diamond is a python daemon that collects metrics
Diamond is a Python daemon that collects metrics
and publishes them to Graphite or other backends.
It is capable of collecting CPU, memory, network, I/O, load, and disk metrics.
Additionally, it features an API for implementing custom collectors
@@ -36,7 +36,7 @@ reading. Each one of these projects is a paragon of Python coding.
applications and has become one of the most advanced WSGI utility modules.
It includes a powerful debugger, full-featured request and response objects,
HTTP utilities to handle entity tags, cache control headers, HTTP dates,
cookie handling, file uploads, a powerful URL routing system and a bunch
cookie handling, file uploads, a powerful URL routing system, and a bunch
of community-contributed addon modules.
- `Requests <https://github.com/kennethreitz/requests>`_
@@ -49,4 +49,4 @@ reading. Each one of these projects is a paragon of Python coding.
.. todo:: Include code examples of exemplary code from each of the projects listed. Explain why it is excellent code. Use complex examples.
.. todo:: Explain techniques to rapidly identify data structures, algorithms and determine what the code is doing.
.. todo:: Explain techniques to rapidly identify data structures and algorithms and determine what the code is doing.
+12 -12
View File
@@ -211,7 +211,7 @@ I highly recommend the latter. Requiring a developer to run
codebase also requires them to have an isolated environment setup for
each instance of the codebase.
To give the individual tests import context, create a tests/context.py
To give the individual tests import context, create a ``tests/context.py``
file:
::
@@ -247,8 +247,8 @@ Makefile
If you look at most of my projects or any Pocoo project, you'll notice a
Makefile laying around. Why? These projects aren't written in C... In
short, make is a incredibly useful tool for defining generic tasks for
Makefile lying around. Why? These projects aren't written in C... In
short, make is an incredibly useful tool for defining generic tasks for
your project.
**Sample Makefile:**
@@ -334,7 +334,7 @@ include:
- Multiple and messy circular dependencies: if your classes
Table and Chair in :file:`furn.py` need to import Carpenter from
:file:`workers.py` to answer a question such as ``table.isdoneby()``,
and if conversely the class Carpenter needs to import Table and Chair,
and if conversely the class Carpenter needs to import Table and Chair
to answer the question ``carpenter.whatdo()``, then you
have a circular dependency. In this case you will have to resort to
fragile hacks such as using import statements inside
@@ -402,7 +402,7 @@ If you'd like you could name your module :file:`my_spam.py`, but even our
friend the underscore should not be seen often in module names. However, using other
characters (spaces or hyphens) in module names will prevent importing
(- is the subtract operator), so try to keep module names short so there is
no need to separate words. And, most of all, don't namespace with underscores, use submodules instead.
no need to separate words. And, most of all, don't namespace with underscores; use submodules instead.
.. code-block:: python
@@ -473,7 +473,7 @@ typing.
As mentioned in the :ref:`code_style` section, readability is one of the main
features of Python. Readability means to avoid useless boilerplate text and
clutter, therefore some efforts are spent trying to achieve a certain level of
clutter; therefore some efforts are spent trying to achieve a certain level of
brevity. But terseness and obscurity are the limits where brevity should stop.
Being able to tell immediately where a class or function comes from, as in the
``modu.func`` idiom, greatly improves code readability and understandability in
@@ -494,7 +494,7 @@ used to gather all package-wide definitions.
A file :file:`modu.py` in the directory :file:`pack/` is imported with the
statement ``import pack.modu``. This statement will look for an
:file:`__init__.py` file in :file:`pack`, execute all of its top-level
:file:`__init__.py` file in :file:`pack` and execute all of its top-level
statements. Then it will look for a file named :file:`pack/modu.py` and
execute all of its top-level statements. After these operations, any variable,
function, or class defined in :file:`modu.py` is available in the pack.modu
@@ -549,9 +549,9 @@ programming, comes from the "state" part of the equation.
In some architectures, typically web applications, multiple instances of Python
processes are spawned to respond to external requests that can happen at the
same time. In this case, holding some state into instantiated objects, which
same time. In this case, holding some state in instantiated objects, which
means keeping some static information about the world, is prone to concurrency
problems or race-conditions. Sometimes, between the initialization of the state
problems or race conditions. Sometimes, between the initialization of the state
of an object (usually done with the ``__init__()`` method) and the actual use
of the object state through one of its methods, the world may have changed, and
the retained state may be outdated. For example, a request may load an item in
@@ -580,7 +580,7 @@ logic (called pure functions) allow the following benefits:
- Pure functions are much easier to change or replace if they need to
be refactored or optimized.
- Pure functions are easier to test with unit-tests: There is less
- Pure functions are easier to test with unit tests: There is less
need for complex context setup and data cleaning afterwards.
- Pure functions are easier to manipulate, decorate, and pass around.
@@ -622,7 +622,7 @@ clearer and thus preferred.
# bar() is decorated
This mechanism is useful for separating concerns and avoiding
external un-related logic 'polluting' the core logic of the function
external unrelated logic 'polluting' the core logic of the function
or method. A good example of a piece of functionality that is better handled
with decoration is `memoization <https://en.wikipedia.org/wiki/Memoization#Overview>`__ or caching: you want to store the results of an
expensive function in a table and use them directly instead of recomputing
@@ -874,7 +874,7 @@ like above or in cases where you are adding to an existing string, using
.. note::
You can also use the :ref:`% <python:string-formatting>` formatting operator
to concatenate a pre-determined number of strings besides :py:meth:`str.join`
and ``+``. However, :pep:`3101`, discourages the usage of the ``%`` operator
and ``+``. However, :pep:`3101` discourages the usage of the ``%`` operator
in favor of the :py:meth:`str.format` method.
.. code-block:: python
+23 -23
View File
@@ -115,7 +115,7 @@ compared to the more straightforward calls to ``send('Hello', 'World')`` and
optional, and evaluate to ``None`` when they are not passed another value.
Calling a function with keyword arguments can be done in multiple ways in
Python, for example it is possible to follow the order of arguments in the
Python; for example, it is possible to follow the order of arguments in the
definition without explicitly naming the arguments, like in
``send('Hello', 'World', 'Cthulhu', 'God')``, sending a blind carbon copy to
God. It would also be possible to name arguments in another order, like in
@@ -124,7 +124,7 @@ possibilities are better avoided without any strong reason to not follow the
syntax that is the closest to the function definition:
``send('Hello', 'World', cc='Cthulhu', bcc='God')``.
As a side note, following `YAGNI <http://en.wikipedia.org/wiki/You_ain't_gonna_need_it>`_
As a side note, following the `YAGNI <http://en.wikipedia.org/wiki/You_ain't_gonna_need_it>`_
principle, it is often harder to remove an optional argument (and its logic
inside the function) that was added "just in case" and is seemingly never used,
than to add a new optional argument and its logic when needed.
@@ -134,7 +134,7 @@ than to add a new optional argument and its logic when needed.
an extensible number of positional arguments, it can be defined with the
``*args`` constructs. In the function body, ``args`` will be a tuple of all
the remaining positional arguments. For example, ``send(message, *args)``
can be called with each recipient as an argument:``send('Hello', 'God',
can be called with each recipient as an argument: ``send('Hello', 'God',
'Mom', 'Cthulhu')``, and in the function body ``args`` will be equal to
``('God', 'Mom', 'Cthulhu')``.
@@ -181,7 +181,7 @@ possible to do each of the following:
* change how the Python interpreter imports modules
* it is even possible (and recommended if needed) to embed C routines in Python.
* It is even possible (and recommended if needed) to embed C routines in Python.
However, all these options have many drawbacks and it is always better to use
the most straightforward way to achieve your goal. The main drawback is that
@@ -208,7 +208,7 @@ are all responsible users".
This doesn't mean that, for example, no properties are considered private, and
that no proper encapsulation is possible in Python. Rather, instead of relying
on concrete walls erected by the developers between their code and other's, the
on concrete walls erected by the developers between their code and others', the
Python community prefers to rely on a set of conventions indicating that these
elements should not be accessed directly.
@@ -359,7 +359,7 @@ Instead, use a list comprehension:
four_lists = [[] for __ in xrange(4)]
Note: Use range() instead of xrange() in Python 3
Note: Use range() instead of xrange() in Python 3.
Create a string from a list
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -462,7 +462,7 @@ group <http://artifex.org/~hblanks/talks/2011/pep20_by_example.pdf>`_.
PEP 8
*****
:pep:`8` is the de-facto code style guide for Python. A high quality,
:pep:`8` is the de facto code style guide for Python. A high quality,
easy-to-read version of PEP 8 is also available at `pep8.org <http://pep8.org/>`_.
This is highly recommended reading. The entire Python community does their
@@ -520,10 +520,10 @@ Conventions
Here are some conventions you should follow to make your code easier to read.
Check if variable equals a constant
Check if a variable equals a constant
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You don't need to explicitly compare a value to True, or None, or 0 - you can
You don't need to explicitly compare a value to True, or None, or 0 -- you can
just add it to the if statement. See `Truth Value Testing
<http://docs.python.org/library/stdtypes.html#truth-value-testing>`_ for a
list of what is considered false.
@@ -608,7 +608,7 @@ Never remove items from a list while you are iterating through it.
a.remove(i)
Don't make multiple passes through the list.
.. code-block:: python
while i in a:
@@ -617,7 +617,7 @@ Don't make multiple passes through the list.
**Good**:
Python has a few standard ways of filtering lists.
The approach you use depends on
The approach you use depends on:
* Python 2.x vs. 3.x
* Lists vs. iterators
@@ -626,19 +626,19 @@ The approach you use depends on
Python 2.x vs. 3.x
::::::::::::::::::
Starting with Python 3.0, the :py:func:`filter` function returns an iterator instead of a list.
Starting with Python 3.0, the :py:func:`filter` function returns an iterator instead of a list.
Wrap it in :py:func:`list` if you truly need a list.
.. code-block:: python
list(filter(...))
List comprehensions and generator expressions work the same in both 2.x and 3.x (except that comprehensions in 2.x "leak" variables into the enclosing namespace)
List comprehensions and generator expressions work the same in both 2.x and 3.x (except that comprehensions in 2.x "leak" variables into the enclosing namespace):
* comprehensions create a new list object
* generators iterate over the original list
* Comprehensions create a new list object.
* Generators iterate over the original list.
The :py:func:`filter` function
The :py:func:`filter` function:
* in 2.x returns a list (use itertools.ifilter if you want an iterator)
* in 3.x returns an iterator
@@ -653,14 +653,14 @@ Creating a new list requires more work and uses more memory. If you a just going
# comprehensions create a new list object
filtered_values = [value for value in sequence if value != x]
# Or (2.x)
filtered_values = filter(lambda i: i != x, sequence)
filtered_values = filter(lambda i: i != x, sequence)
# generators don't create another list
filtered_values = (value for value in sequence if value != x)
# Or (3.x)
filtered_values = filter(lambda i: i != x, sequence)
# Or (2.x)
filtered_values = itertools.ifilter(lambda i: i != x, sequence)
filtered_values = itertools.ifilter(lambda i: i != x, sequence)
@@ -678,7 +678,7 @@ Modifying the original list can be risky if there are other variables referencin
# Or
sequence[::] = filter(lambda value: value != x, sequence)
Modifying the values in a list
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Bad**:
@@ -690,26 +690,26 @@ Remember that assignment never creates a new object. If two or more variables re
# Add three to all list members.
a = [3, 4, 5]
b = a # a and b refer to the same list object
for i in range(len(a)):
a[i] += 3 # b[i] also changes
**Good**:
It's safer to create a new list object and leave the original alone.
It's safer to create a new list object and leave the original alone.
.. code-block:: python
a = [3, 4, 5]
b = a
# assign the variable "a" to a new list without changing "b"
a = [i + 3 for i in a]
# Or (Python 2.x):
a = map(lambda i: i + 3, a)
# Or (Python 3.x)
a = list(map(lambda i: i + 3, a))
Use :py:func:`enumerate` keep a count of your place in the list.
+5 -6
View File
@@ -81,7 +81,7 @@ The Basics
**********
Unittest
unittest
--------
:mod:`unittest` is the batteries-included test module in the Python standard
@@ -170,7 +170,7 @@ functions:
def test_answer():
assert func(3) == 5
and then running the `py.test` command
and then running the `py.test` command:
.. code-block:: console
@@ -236,14 +236,14 @@ tox
---
tox is a tool for automating test environment management and testing against
multiple interpreter configurations
multiple interpreter configurations.
.. code-block:: console
$ pip install tox
tox allows you to configure complicated multi-parameter test matrices via a
simple ini-style configuration file.
simple INI-style configuration file.
`tox <https://tox.readthedocs.io/en/latest/>`_
@@ -254,7 +254,7 @@ Unittest2
unittest2 is a backport of Python 2.7's unittest module which has an improved
API and better assertions over the one available in previous versions of Python.
If you're using Python 2.6 or below, you can install it with pip
If you're using Python 2.6 or below, you can install it with pip:
.. code-block:: console
@@ -326,4 +326,3 @@ always returns the same result (but only for the duration of the test).
Mock has many other ways you can configure it and control its behavior.
`mock <http://www.voidspace.org.uk/python/mock/>`_