Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion docs/writing/documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,26 +104,38 @@ line. Good editors allow to do this with few keystrokes (ctrl-v on Vim).

def tricky_function():
'''
Commented out because its breaks something.
if foo:
do_bar()
'''
return baz

def tricky_function():
# Commented out because its breaks something.
#if foo:
#do_bar()
return baz


def tricky_function():
# Commented out because its breaks something.
# if foo:
# do_bar()
return baz

**Good**

.. code-block:: python

def tricky_function():
# Commented out because its breaks something.
#if foo:
# do_bar()
return baz


Note that comment text is properly written and separated from the hash by a
space. Commented code is not separated from the hash by an additional space;
this helps when uncommented the code.

The Basics
::::::::::
Expand Down
77 changes: 77 additions & 0 deletions docs/writing/structure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,83 @@ Lastly, a convenient syntax is available for importing deeply nested packages:
`import very.deep.module as mod` allow to use `mod` in place of the verbose
repetition of `very.deep.module` in front of each calls to module items.

Object-oriented programming
---------------------------

Python is sometime described as an object-oriented programming language. This
can be somewhat misleading and need to be clarified.

In Python, everything is an object, and can be handled as such. This is what is
meant when we say that, for example, functions are first-class objects.
Functions, classes, strings, and even types are objects in Python: like any
objects, they have a type, they can be passed as function arguments, they may
have methods and properties. In this understanding, Python is an
object-oriented language.

However, unlike Java, Python do not impose object-oriented programming as the
main programming paradigm. It is perfectly viable for a Python project to not
be object-oriented, ie. to use no or very few class definitions, class
inheritance, and any other mechanism that are specific to object-oriented
programming.

Moreover, as seen in the modules_ section, the way Python handles modules and
namespaces gives directly to the developer a natural way to ensure
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
model to be constructed.

There are some reasons to avoid unnecessary object-orientation. Definining
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
programming, comes from the "state" part of the equation.

In some architectures, typically web applications, instances of Python
processes are spawned simultaneously to answer to external requests that can
happen at the same time. In this case, holding some state into instanciated
objects, which means keeping some static information about the world, is prone
to concurrency problems or race-conditions: 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 method, 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, it may happen that the deletion actually occur after
the first process loaded the item, and then we have to mark as read a deleted
object.

This and other issues led to the idea that using stateless functions is a
better programming paradigm.

Another way to say the same thing is to propose to use functions and procedures
with as few implicit context and side-effects as possible. A function's
implicit context is decelable when the function body refers to some global
variables or fetches data from the persistence layer. Side-effects are the
opposite: if a function body modifies the global context or save or delete data
on the persistence layer, it is said to have side-effect.

Isolating carefully functions with context and side-effects from functions with
logic (called pure functions) allow the following benefits:

- Pure functions are more likely to be deterministic: given a fixed input,
the output will always be the same.

- 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
need for complex context setup and data cleaning afterwards.

- Pure functions are easier to manipulate, decorate_, pass-around.

In summary, pure functions, without any context or side-effects, are more
efficient building blocks than classes and objects for some architectures.

Obviously, object-orientation is useful and even necessary in many cases, for
example when developing graphical desktop applications or games, where the
things that are manipulated (windows, buttons, avatars, vehicles) have a
relatively long life of their own in the computer's memory.


Vendorizing Dependencies
------------------------

Expand Down