mirror of
https://github.com/kennethreitz/python-guide.git
synced 2026-06-05 06:46:17 +00:00
Merge pull request #1085 from aviranzerioniac/master
Minor changes to few sentences.
This commit is contained in:
+3
-3
@@ -4,7 +4,7 @@
|
||||
contain the root `toctree` directive.
|
||||
|
||||
.. meta::
|
||||
:description: An opinionated guide to the Python programming language and a best practice handbook to the installation, configuration, and usage of Python on a daily basis.
|
||||
:description: An opinionated guide to the Python programming language and a best practice handbook for the installation, configuration, and usage of Python on a daily basis.
|
||||
|
||||
|
||||
#################################
|
||||
@@ -17,7 +17,7 @@ Greetings, Earthling! Welcome to The Hitchhiker's Guide to Python.
|
||||
`fork us on GitHub <https://github.com/realpython/python-guide>`_!
|
||||
|
||||
This handcrafted guide exists to provide both novice and expert Python
|
||||
developers a best practice handbook to the installation, configuration, and
|
||||
developers a best practice handbook for the installation, configuration, and
|
||||
usage of Python on a daily basis.
|
||||
|
||||
This guide is **opinionated** in a way that is almost, but not quite, entirely
|
||||
@@ -25,7 +25,7 @@ This guide is **opinionated** in a way that is almost, but not quite, entirely
|
||||
available here. Rather, you'll find a nice concise list of highly recommended
|
||||
options.
|
||||
|
||||
.. note:: The use of **Python 3** is *highly* preferred over Python 2. Consider upgrading your applications and infrastructure if you find yourself *still* using Python 2 in production today. If you are using Python 3, congratulations — you are indeed a person of excellent taste.
|
||||
.. note:: The use of **Python 3** is *highly* recommended over Python 2. Consider upgrading your applications and infrastructures if you find yourself *still* using Python 2 in production today. If you are using Python 3, congratulations — you are indeed a person of excellent taste.
|
||||
—*Kenneth Reitz*
|
||||
|
||||
Let's get started! But first, let's make sure you know where your towel is.
|
||||
|
||||
@@ -199,7 +199,7 @@ Ansible
|
||||
*******
|
||||
|
||||
`Ansible <http://ansible.com/>`_ is an open source system automation tool.
|
||||
The biggest advantage over Puppet or Chef is it does not require an agent on
|
||||
Its biggest advantage over Puppet or Chef is that it does not require an agent on
|
||||
the client machine. Playbooks are Ansible’s configuration, deployment, and
|
||||
orchestration language and are written in YAML with Jinja2 for templating.
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ Travis-CI
|
||||
tests for open source projects for free. It provides multiple workers to run
|
||||
Python tests on and seamlessly integrates with GitHub. You can even have it
|
||||
comment on your Pull Requests whether this particular changeset breaks the
|
||||
build or not. So if you are hosting your code on GitHub, Travis-CI is a great
|
||||
build or not. So, if you are hosting your code on GitHub, Travis-CI is a great
|
||||
and easy way to get started with Continuous Integration.
|
||||
|
||||
In order to get started, add a :file:`.travis.yml` file to your repository with
|
||||
|
||||
@@ -31,7 +31,7 @@ Recommendations
|
||||
***************
|
||||
|
||||
|
||||
.. note:: The use of **Python 3** is *highly* preferred over Python 2. Consider upgrading your applications and infrastructure if you find yourself *still* using Python 2 in production today. If you are using Python 3, congratulations — you are indeed a person of excellent taste.
|
||||
.. note:: The use of **Python 3** is *highly* recommended over Python 2. Consider upgrading your applications and infrastructure if you find yourself *still* using Python 2 in production today. If you are using Python 3, congratulations — you are indeed a person of excellent taste.
|
||||
—*Kenneth Reitz*
|
||||
|
||||
I'll be blunt:
|
||||
|
||||
@@ -45,7 +45,7 @@ Project Publication
|
||||
Depending on the project, your documentation might include some or all
|
||||
of the following components:
|
||||
|
||||
- An *introduction* should show a very short overview of what can be
|
||||
- An *introduction* should give a very short overview of what can be
|
||||
done with the product, using one or two extremely simplified use
|
||||
cases. This is the thirty-second pitch for your project.
|
||||
|
||||
@@ -94,7 +94,7 @@ reStructuredText
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Most Python documentation is written with reStructuredText_. It's like
|
||||
Markdown with all the optional extensions built in.
|
||||
Markdown, but with all the optional extensions built in.
|
||||
|
||||
The `reStructuredText Primer`_ and the `reStructuredText Quick
|
||||
Reference`_ should help you familiarize yourself with its syntax.
|
||||
@@ -149,8 +149,8 @@ a project's documentation.
|
||||
Additionally, Doctest_ will read all embedded docstrings that look like input
|
||||
from the Python commandline (prefixed with ">>>") and run them, checking to see
|
||||
if the output of the command matches the text on the following line. This
|
||||
allows developers to embed real examples and usage of functions alongside
|
||||
their source code, and as a side effect, it also ensures that their code is
|
||||
allows developers to embed real examples and usage of functions alongside
|
||||
their source code. As a side effect, it also ensures that their code is
|
||||
tested and works.
|
||||
|
||||
::
|
||||
@@ -187,8 +187,8 @@ Docstrings are accessible from both the `__doc__` dunder attribute for almost
|
||||
every Python object, as well as with the built in `help()` function.
|
||||
|
||||
While block comments are usually used to explain *what* a section of code is
|
||||
doing, or the specifics of an algorithm, docstrings are more intended for
|
||||
explaining to other users of your code (or you in 6 months time) *how* a
|
||||
doing, or the specifics of an algorithm, docstrings are more intended towards
|
||||
explaining other users of your code (or you in 6 months time) *how* a
|
||||
particular function can be used and the general purpose of a function, class,
|
||||
or module.
|
||||
|
||||
@@ -214,7 +214,7 @@ In larger or more complex projects however, it is often a good idea to give
|
||||
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
|
||||
For more detailed documentation of code a popular style used, is the one used by the
|
||||
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. ::
|
||||
|
||||
@@ -7,13 +7,13 @@ Common Gotchas
|
||||
.. image:: /_static/photos/34435688380_b5a740762b_k_d.jpg
|
||||
|
||||
For the most part, Python aims to be a clean and consistent language that
|
||||
avoids surprises. However, there are a few cases that can be confusing to
|
||||
avoids surprises. However, there are a few cases that can be confusing for
|
||||
newcomers.
|
||||
|
||||
Some of these cases are intentional but can be potentially surprising. Some
|
||||
could arguably be considered language warts. In general, what follows
|
||||
is a collection of potentially tricky behavior that might seem strange at first
|
||||
glance, but is generally sensible once you're aware of the underlying cause for
|
||||
glance, but are generally sensible, once you're aware of the underlying cause for
|
||||
the surprise.
|
||||
|
||||
|
||||
@@ -53,8 +53,8 @@ isn't provided, so that the output is::
|
||||
[12]
|
||||
[42]
|
||||
|
||||
What Does Happen
|
||||
~~~~~~~~~~~~~~~~
|
||||
What Actually Happens
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. testoutput::
|
||||
|
||||
@@ -100,6 +100,7 @@ Late Binding Closures
|
||||
Another common source of confusion is the way Python binds its variables in
|
||||
closures (or in the surrounding global scope).
|
||||
|
||||
|
||||
What You Wrote
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
@@ -125,8 +126,8 @@ variable that multiplies their argument, producing::
|
||||
6
|
||||
8
|
||||
|
||||
What Does Happen
|
||||
~~~~~~~~~~~~~~~~
|
||||
What Actually Happens
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. testoutput::
|
||||
|
||||
@@ -206,7 +207,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.
|
||||
Without these bytecode files present, Python would re-generate the bytecode
|
||||
Without these bytecode files, Python would re-generate the bytecode
|
||||
every time the file is loaded.
|
||||
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ Choosing a License
|
||||
|
||||
.. image:: /_static/photos/33907149294_82d7535a6c_k_d.jpg
|
||||
|
||||
Your source publication *needs* a license. In the US, if no license is
|
||||
specified, users have no legal right to download, modify, or distribute.
|
||||
Your source publication *needs* a license. In the US, unless a license is
|
||||
specified, users have no legal right to download, modify, or distribute the product.
|
||||
Furthermore, people can't contribute to your code unless you tell them what
|
||||
rules to play by. Choosing a license is complicated, so here are some pointers:
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ The :mod:`logging` module has been a part of Python's Standard Library since
|
||||
version 2.3. It is succinctly described in :pep:`282`. The documentation
|
||||
is notoriously hard to read, except for the `basic logging tutorial`_.
|
||||
|
||||
As an alternative, `loguru <https://github.com/Delgan/loguru>`_ provides an approach to logging nearly as simple as using a simple ``print`` statement.
|
||||
As an alternative, `loguru <https://github.com/Delgan/loguru>`_ provides an approach for logging, nearly as simple as using a simple ``print`` statement.
|
||||
|
||||
Logging serves two purposes:
|
||||
|
||||
@@ -59,7 +59,7 @@ using the ``__name__`` global variable: the :mod:`logging` module creates a
|
||||
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
|
||||
Here is an example of the best practice from the `requests source`_ -- place
|
||||
this in your ``__init__.py``:
|
||||
|
||||
.. code-block:: python
|
||||
@@ -83,7 +83,7 @@ application environment.
|
||||
There are at least three ways to configure a logger:
|
||||
|
||||
- Using an INI-formatted file:
|
||||
- **Pro**: possible to update configuration while running using the
|
||||
- **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)
|
||||
than possible when configuring a logger in code.
|
||||
@@ -94,13 +94,13 @@ There are at least three ways to configure a logger:
|
||||
- **Con**: less control than when configuring a logger in code.
|
||||
- Using code:
|
||||
- **Pro**: complete control over the configuration.
|
||||
- **Con**: modifications require a change to source code.
|
||||
- **Con**: modifications require a change to the source code.
|
||||
|
||||
|
||||
Example Configuration via an INI File
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Let us say the file is named ``logging_config.ini``.
|
||||
Let us say that the file is named ``logging_config.ini``.
|
||||
More details for the file format are in the `logging configuration`_
|
||||
section of the `logging tutorial`_.
|
||||
|
||||
|
||||
+45
-47
@@ -18,7 +18,7 @@ the project? What features and functions can be grouped together and
|
||||
isolated? By answering questions like these you can begin to plan, in
|
||||
a broad sense, what your finished product will look like.
|
||||
|
||||
In this section we take a closer look at Python's module and import
|
||||
In this section, we take a closer look at Python's modules and import
|
||||
systems as they are the central elements to enforcing structure in your
|
||||
project. We then discuss various perspectives on how to build code which
|
||||
can be extended and tested reliably.
|
||||
@@ -32,7 +32,7 @@ It's Important.
|
||||
:::::::::::::::
|
||||
|
||||
Just as Code Style, API Design, and Automation are essential for a
|
||||
healthy development cycle, Repository structure is a crucial part of
|
||||
healthy development cycle. Repository structure is a crucial part of
|
||||
your project's
|
||||
`architecture <http://www.amazon.com/gp/product/1257638017/ref=as_li_ss_tl?ie=UTF8&tag=bookforkind-20&linkCode=as2&camp=1789&creative=39095&creativeASIN=1257638017>`__.
|
||||
|
||||
@@ -54,8 +54,7 @@ documentation.
|
||||
|
||||
Of course, first impressions aren't everything. You and your colleagues
|
||||
will spend countless hours working with this repository, eventually
|
||||
becoming intimately familiar with every nook and cranny. The layout of
|
||||
it is important.
|
||||
becoming intimately familiar with every nook and cranny. The layout is important.
|
||||
|
||||
Sample Repository
|
||||
:::::::::::::::::
|
||||
@@ -126,7 +125,7 @@ If you aren't sure which license you should use for your project, check
|
||||
out `choosealicense.com <http://choosealicense.com>`_.
|
||||
|
||||
Of course, you are also free to publish code without a license, but this
|
||||
would prevent many people from potentially using your code.
|
||||
would prevent many people from potentially using or contributing to your code.
|
||||
|
||||
Setup.py
|
||||
::::::::
|
||||
@@ -157,8 +156,8 @@ should be placed at the root of the repository. It should specify the
|
||||
dependencies required to contribute to the project: testing, building,
|
||||
and generating documentation.
|
||||
|
||||
If your project has no development dependencies, or you prefer
|
||||
development environment setup via ``setup.py``, this file may be
|
||||
If your project has no development dependencies, or if you prefer
|
||||
setting up a development environment via ``setup.py``, this file may be
|
||||
unnecessary.
|
||||
|
||||
Documentation
|
||||
@@ -331,42 +330,42 @@ Easy structuring of a project means it is also easy
|
||||
to do it poorly. Some signs of a poorly structured project
|
||||
include:
|
||||
|
||||
- Multiple and messy circular dependencies: if your classes
|
||||
- Multiple and messy circular dependencies: If the 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
|
||||
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
|
||||
fragile hacks such as using import statements inside your
|
||||
methods or functions.
|
||||
|
||||
- Hidden coupling: each and every change in Table's implementation
|
||||
- Hidden coupling: Each and every change in Table's implementation
|
||||
breaks 20 tests in unrelated test cases because it breaks Carpenter's code,
|
||||
which requires very careful surgery to adapt the change. This means
|
||||
which requires very careful surgery to adapt to the change. This means
|
||||
you have too many assumptions about Table in Carpenter's code or the
|
||||
reverse.
|
||||
|
||||
- Heavy usage of global state or context: instead of explicitly
|
||||
- Heavy usage of global state or context: Instead of explicitly
|
||||
passing ``(height, width, type, wood)`` to each other, Table
|
||||
and Carpenter rely on global variables that can be modified
|
||||
and are modified on the fly by different agents. You need to
|
||||
scrutinize all access to these global variables to understand why
|
||||
scrutinize all access to these global variables in order to understand why
|
||||
a rectangular table became a square, and discover that remote
|
||||
template code is also modifying this context, messing with
|
||||
table dimensions.
|
||||
the table dimensions.
|
||||
|
||||
- Spaghetti code: multiple pages of nested if clauses and for loops
|
||||
with a lot of copy-pasted procedural code and no
|
||||
proper segmentation are known as spaghetti code. Python's
|
||||
meaningful indentation (one of its most controversial features) make
|
||||
it very hard to maintain this kind of code. So the good news is that
|
||||
meaningful indentation (one of its most controversial features) makes
|
||||
it very hard to maintain this kind of code. The good news is that
|
||||
you might not see too much of it.
|
||||
|
||||
- Ravioli code is more likely in Python: it consists of hundreds of
|
||||
similar little pieces of logic, often classes or objects, without
|
||||
proper structure. If you never can remember if you have to use
|
||||
proper structure. If you never can remember, if you have to use
|
||||
FurnitureTable, AssetTable or Table, or even TableNew for your
|
||||
task at hand, you might be swimming in ravioli code.
|
||||
task at hand, then you might be swimming in ravioli code.
|
||||
|
||||
|
||||
*******
|
||||
@@ -384,13 +383,13 @@ in one file, and all low-level operations in another file. In this case,
|
||||
the interface file needs to import the low-level file. This is done with the
|
||||
``import`` and ``from ... import`` statements.
|
||||
|
||||
As soon as you use `import` statements you use modules. These can be either
|
||||
As soon as you use `import` statements, you use modules. These can be either
|
||||
built-in modules such as `os` and `sys`, third-party modules you have installed
|
||||
in your environment, or your project's internal modules.
|
||||
|
||||
To keep in line with the style guide, keep module names short, lowercase, and
|
||||
be sure to avoid using special symbols like the dot (.) or question mark (?).
|
||||
So a file name like :file:`my.spam.py` is one you should avoid! Naming this way
|
||||
A file name like :file:`my.spam.py` is the one you should avoid! Naming this way
|
||||
will interfere with the way Python looks for modules.
|
||||
|
||||
In the case of `my.spam.py` Python expects to find a :file:`spam.py` file in a
|
||||
@@ -398,10 +397,10 @@ folder named :file:`my` which is not the case. There is an
|
||||
`example <http://docs.python.org/tutorial/modules.html#packages>`_ of how the
|
||||
dot notation should be used in the Python docs.
|
||||
|
||||
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
|
||||
If you like, you could name your module :file:`my_spam.py`, but even our trusty
|
||||
friend the underscore, should not be seen that 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
|
||||
(- is the subtract operator). 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.
|
||||
|
||||
.. code-block:: python
|
||||
@@ -412,15 +411,15 @@ no need to separate words. And, most of all, don't namespace with underscores; u
|
||||
import library.foo_plugin
|
||||
|
||||
Aside from some naming restrictions, nothing special is required for a Python
|
||||
file to be a module, but you need to understand the import mechanism in order
|
||||
file to be a module. But you need to understand the import mechanism in order
|
||||
to use this concept properly and avoid some issues.
|
||||
|
||||
Concretely, the ``import modu`` statement will look for the proper file, which
|
||||
is :file:`modu.py` in the same directory as the caller if it exists. If it is
|
||||
is :file:`modu.py` in the same directory as the caller, if it exists. If it is
|
||||
not found, the Python interpreter will search for :file:`modu.py` in the "path"
|
||||
recursively and raise an ImportError exception if it is not found.
|
||||
recursively and raise an ImportError exception when it is not found.
|
||||
|
||||
Once :file:`modu.py` is found, the Python interpreter will execute the module in
|
||||
When :file:`modu.py` is found, the Python interpreter will execute the module in
|
||||
an isolated scope. Any top-level statement in :file:`modu.py` will be executed,
|
||||
including other imports if any. Function and class definitions are stored in
|
||||
the module's dictionary.
|
||||
@@ -437,7 +436,7 @@ unwanted effects, e.g. override an existing function with the same name.
|
||||
|
||||
It is possible to simulate the more standard behavior by using a special syntax
|
||||
of the import statement: ``from modu import *``. This is generally considered
|
||||
bad practice. **Using** ``import *`` **makes code harder to read and makes
|
||||
bad practice. **Using** ``import *`` **makes the code harder to read and makes
|
||||
dependencies less compartmentalized**.
|
||||
|
||||
Using ``from modu import func`` is a way to pinpoint the function you want to
|
||||
@@ -493,20 +492,20 @@ modules, but with a special behavior for the :file:`__init__.py` file, which is
|
||||
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
|
||||
statement ``import pack.modu``. This statement will look for
|
||||
: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
|
||||
namespace.
|
||||
|
||||
A commonly seen issue is to add too much code to :file:`__init__.py`
|
||||
A commonly seen issue is adding too much code to :file:`__init__.py`
|
||||
files. When the project complexity grows, there may be sub-packages and
|
||||
sub-sub-packages in a deep directory structure. In this case, importing a
|
||||
single item from a sub-sub-package will require executing all
|
||||
:file:`__init__.py` files met while traversing the tree.
|
||||
|
||||
Leaving an :file:`__init__.py` file empty is considered normal and even a good
|
||||
Leaving an :file:`__init__.py` file empty is considered normal and even good
|
||||
practice, if the package's modules and sub-packages do not need to share any
|
||||
code.
|
||||
|
||||
@@ -520,45 +519,44 @@ Object-oriented programming
|
||||
***************************
|
||||
|
||||
Python is sometimes described as an object-oriented programming language. This
|
||||
can be somewhat misleading and needs to be clarified.
|
||||
can be somewhat misleading and requires further clarifications.
|
||||
|
||||
In Python, everything is an object, and can be handled as such. This is what is
|
||||
meant when we say, for example, that functions are first-class objects.
|
||||
Functions, classes, strings, and even types are objects in Python: like any
|
||||
object, they have a type, they can be passed as function arguments, and they
|
||||
may have methods and properties. In this understanding, Python is an
|
||||
object-oriented language.
|
||||
may have methods and properties. In this understanding, Python can be considered
|
||||
as an object-oriented language.
|
||||
|
||||
However, unlike Java, Python does not impose object-oriented programming as the
|
||||
main programming paradigm. It is perfectly viable for a Python project to not
|
||||
be object-oriented, i.e. to use no or very few class definitions, class
|
||||
inheritance, or any other mechanisms that are specific to object-oriented
|
||||
programming.
|
||||
programming languages.
|
||||
|
||||
Moreover, as seen in the modules_ section, the way Python handles modules and
|
||||
namespaces gives the developer a natural way to ensure the
|
||||
encapsulation and separation of abstraction layers, both being the most common
|
||||
reasons to use object-orientation. Therefore, Python programmers have more
|
||||
latitude to not use object-orientation, when it is not required by the business
|
||||
latitude as to not use object-orientation, when it is not required by the business
|
||||
model.
|
||||
|
||||
There are some reasons to avoid unnecessary object-orientation. Defining
|
||||
custom classes is useful when we want to glue together some state and some
|
||||
functionality. The problem, as pointed out by the discussions about functional
|
||||
custom classes is useful when we want to glue some state and some
|
||||
functionality together. The problem, as pointed out by the discussions about functional
|
||||
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 in instantiated objects, which
|
||||
processes are spawned as a response to external requests that happen simultaneously.
|
||||
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
|
||||
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
|
||||
memory and mark it as read by a user. If another request requires the deletion
|
||||
of this item at the same time, it may happen that the deletion actually occurs
|
||||
after the first process loaded the item, and then we have to mark as read a
|
||||
deleted object.
|
||||
of this item at the same time, the deletion may actually occur after the first
|
||||
process loaded the item, and then we have to mark a deleted object as read.
|
||||
|
||||
This and other issues led to the idea that using stateless functions is a
|
||||
better programming paradigm.
|
||||
@@ -572,7 +570,7 @@ or deletes data in a global variable or in the persistence layer, it is said to
|
||||
have a side-effect.
|
||||
|
||||
Carefully isolating functions with context and side-effects from functions with
|
||||
logic (called pure functions) allow the following benefits:
|
||||
logic (called pure functions) allows the following benefits:
|
||||
|
||||
- Pure functions are deterministic: given a fixed input,
|
||||
the output will always be the same.
|
||||
@@ -714,7 +712,7 @@ type. In fact, in Python, variables are very different from what they are in
|
||||
many other languages, specifically statically-typed languages. Variables are not
|
||||
a segment of the computer's memory where some value is written, they are 'tags'
|
||||
or 'names' pointing to objects. It is therefore possible for the variable 'a' to
|
||||
be set to the value 1, then to the value 'a string', then to a function.
|
||||
be set to the value 1, then the value 'a string', to a function.
|
||||
|
||||
The dynamic typing of Python is often considered to be a weakness, and indeed
|
||||
it can lead to complexities and hard-to-debug code. Something named 'a' can be
|
||||
@@ -744,7 +742,7 @@ Some guidelines help to avoid this issue:
|
||||
def func():
|
||||
pass # Do something
|
||||
|
||||
Using short functions or methods helps reduce the risk
|
||||
Using short functions or methods helps to reduce the risk
|
||||
of using the same name for two unrelated things.
|
||||
|
||||
It is better to use different names even for things that are related,
|
||||
@@ -846,7 +844,7 @@ most idiomatic way to do this.
|
||||
|
||||
One final thing to mention about strings is that using ``join()`` is not always
|
||||
best. In the instances where you are creating a new string from a pre-determined
|
||||
number of strings, using the addition operator is actually faster, but in cases
|
||||
number of strings, using the addition operator is actually faster. But in cases
|
||||
like above or in cases where you are adding to an existing string, using
|
||||
``join()`` should be your preferred method.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Code Style
|
||||
.. image:: /_static/photos/33907150054_5ee79e8940_k_d.jpg
|
||||
|
||||
If you ask Python programmers what they like most about Python, they will
|
||||
often cite its high readability. Indeed, a high level of readability
|
||||
often cite its high readability. Indeed, a high level of readability
|
||||
is at the heart of the design of the Python language, following the
|
||||
recognized fact that code is read much more often than it is written.
|
||||
|
||||
@@ -226,7 +226,7 @@ but making a public property private might be a much harder operation.
|
||||
Returning values
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
When a function grows in complexity it is not uncommon to use multiple return
|
||||
When a function grows in complexity, it is not uncommon to use multiple return
|
||||
statements inside the function's body. However, in order to keep a clear intent
|
||||
and a sustainable readability level, it is preferable to avoid returning
|
||||
meaningful values from many output points in the body.
|
||||
@@ -639,11 +639,11 @@ Short Ways to Manipulate Lists
|
||||
|
||||
`List comprehensions
|
||||
<http://docs.python.org/tutorial/datastructures.html#list-comprehensions>`_
|
||||
provide a powerful, concise way to work with lists.
|
||||
provides a powerful, concise way to work with lists.
|
||||
|
||||
`Generator expressions
|
||||
<http://docs.python.org/tutorial/classes.html#generator-expressions>`_
|
||||
follow almost the same syntax as list comprehensions but return a generator
|
||||
follows almost the same syntax as list comprehensions but return a generator
|
||||
instead of a list.
|
||||
|
||||
Creating a new list requires more work and uses more memory. If you are just going
|
||||
@@ -829,7 +829,7 @@ a white space added to the end of the line, after the backslash, will break the
|
||||
code and may have unexpected results.
|
||||
|
||||
A better solution is to use parentheses around your elements. Left with an
|
||||
unclosed parenthesis on an end-of-line the Python interpreter will join the
|
||||
unclosed parenthesis on an end-of-line, the Python interpreter will join the
|
||||
next line until the parentheses are closed. The same behavior holds for curly
|
||||
and square braces.
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ Testing Your Code
|
||||
Testing your code is very important.
|
||||
|
||||
Getting used to writing testing code and running this code in parallel is now
|
||||
considered a good habit. Used wisely, this method helps you define more
|
||||
precisely your code's intent and have a more decoupled architecture.
|
||||
considered a good habit. Used wisely, this method helps to define your
|
||||
code's intent more precisely and have a more decoupled architecture.
|
||||
|
||||
Some general rules of testing:
|
||||
|
||||
@@ -294,6 +294,6 @@ always returns the same result (but only for the duration of the test).
|
||||
# get_search_results runs a search and iterates over the result
|
||||
self.assertEqual(len(myapp.get_search_results(q="fish")), 3)
|
||||
|
||||
Mock has many other ways you can configure it and control its behavior.
|
||||
Mock has many other ways with which you can configure and control its behaviour.
|
||||
|
||||
`mock <http://www.voidspace.org.uk/python/mock/>`_
|
||||
|
||||
Reference in New Issue
Block a user