Merge pull request #52 from epequeno/master
authorKenneth Reitz <me@kennethreitz.com>
Fri, 27 Apr 2012 18:36:59 +0000 (11:36 -0700)
committerKenneth Reitz <me@kennethreitz.com>
Fri, 27 Apr 2012 18:36:59 +0000 (11:36 -0700)
Added idioms to style.rst

1  2 
docs/writing/style.rst

  Code Style
  ==========
  
 +If you ask to Python programmers what they like the most in Python, they will
 +often say it is its high readability.  Indeed, a high level of readability of
 +the code is at the heart of the design of the Python language, following the
 +recognised fact that code is read much more often than it is written.
 +
 +One reason for Python code to be easily read and understood is its relatively
 +complete set of Code Style guidelines and "Pythonic" idioms.
 +
 +On the opposite, when a veteran Python developper (a Pythonistas) point to some
 +parts of a code and say it is not "Pythonic", it usually means that these lines
 +of code do not follow the common guidelines and fail to express the intent is
 +what is considered the best (hear: most readable) way.
 +
 +On some border cases, no best way has been agreed upon on how to express
 +an intent in Python code, but these cases are rare.
 +
 +General concepts
 +----------------
 +
 +Explicit code
 +~~~~~~~~~~~~~
 +
 +While any kind of black magic is possible with Python, the
 +most explicit and straightforward manner is preferred.
 +
 +**Bad**
 +
 +.. code-block:: python
 +
 +    def make_complex(\*args):
 +        x, y = args
 +        return dict(\**locals())
 +
 +**Good**
 +
 +.. code-block:: python
 +
 +    def make_complex(x, y):
 +        return {'x': x, 'y': y}
 +
 +In the good code above, x and y are explicitely received from
 +the caller, and an explicit dictionary is returned. The developer
 +using this function knows exactly what to do by reading the
 +first and last lines, which is not the case with the bad example.
 +
 +One statement per line
 +~~~~~~~~~~~~~~~~~~~~~~
 +
 +While some compound statements such as list comprehensions are
 +allowed and appreciated for their brevity and their expressivity,
 +it is bad practice to have two disjoint statements on the same line.
 +
 +**Bad**
 +
 +.. code-block:: python
 +
 +    print 'one'; print 'two'
 +
 +    if x == 1: print 'one'
 +
 +    if <complex comparison> and <other complex comparison>:
 +        # do something
 +
 +**Good**
 +
 +.. code-block:: python
 +
 +    print 'one'
 +    print 'two'
 +
 +    if x == 1:
 +        print 'one'
 +
 +    cond1 = <complex comparison>
 +    cond2 = <other complex comparison>
 +    if cond1 and cond2:
 +        # do something
 +
 +
 +Avoid the magical wand
 +~~~~~~~~~~~~~~~~~~~~~~
 +
 +A powerful tool for hackers, Python comes with a very rich set of hooks and
 +tools allowing to do almost any kind of tricky tricks. For instance, it is
 +possible to change how objects are created and instanciated, it is possible to
 +change how the Python interpreter imports modules, 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
 +readability suffers deeply from them. Many code analysis tools, such as pylint
 +or pyflakes, will be unable to parse this "magic" code.
 +
 +We consider that a Python developer should know about these nearly infinite
 +possibilities, because it grows the confidence that no hard-wall will be on the
 +way.  However, knowing how to use them and particularly when **not** to use
 +them is the most important.
 +
 +Like a Kungfu master, a pythonistas knows how to kill with a single finger, and
 +never do it.
 +
 +We are all consenting adults
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 +
 +As seen above, Python allows many tricks, and some of them are potentially
 +dangerous. A good example is that any client code can override an object's
 +properties and methods: There is no "private" keyword in Python. This
 +philosophy, very different from highly defensive languages like Java, which
 +give a lot of mechanism to prevent any misuse, is expressed by the saying: "We
 +are consenting adults".
 +
 +This doesn't mean that, for example, no properties are considered private, and
 +that no proper encapsulation is possible in Python. But, instead of relying on
 +concrete walls erected by the developers between their code and other's, the
 +Python community prefers to rely on a set of convention indicating that these
 +elements should not be accessed directly.
 +
 +The main convention for private properties and implementation details is to
 +prefix all "internals" with an underscore. If the client code breaks this rule
 +and access to these marked elements, any misbehavior or problems encountered if
 +the code is modified is the responsibility of the client code.
 +
 +Using this convention generously is encouraged: any method or property that is
 +not intended to be used by client code should be prefixed with an underscore.
 +This will guarantee a better separation of duties and easier modifications of
 +existing code, and it will always be possible to publicize a private property,
 +while privatising a public property might be a much harder operation.
  
  Idioms
 -::::::
 +------
 +
 +Idiomatic Python code is often referred to as being *Pythonic*.
 +
 +.. _unpacking-ref:
 +
 +Unpacking
 +~~~~~~~~~
 +
 +If you know the length of a list or tuple, you can assign names to its
 +elements with unpacking:
 +
 +.. code-block:: python
 +
 +    for index, item in enumerate(some_list):
 +        # do something with index and item
 +
 +You can use this to swap variables, as well:
 +
 +.. code-block:: python
 +
 +    a, b = b, a
 +
 +Create an ignored variable
 +~~~~~~~~~~~~~~~~~~~~~~~~~~
 +
 +If you need to assign something (for instance, in :ref:`unpacking-ref`) but
 +will not need that variable, use ``_``:
 +
 +.. code-block:: python
 +
 +    filename = 'foobar.txt'
 +    basename, _, ext = filename.rpartition()
 +
 +.. note::
 +
 +   "``_``" is commonly used as an alias for the :func:`~gettext.gettext`
 +   function. If your application uses (or may someday use) :mod:`gettext`,
 +   you may want to avoid using ``_`` for ignored variables, as you may
 +   accidentally shadow :func:`~gettext.gettext`.
 +
 +Create a length-N list of the same thing
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 +
 +Use the Python list ``*`` operator:
 +
 +.. code-block:: python
 +
 +    four_nones = [None] * 4
 +
 +Create a length-N list of lists
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 +
 +Because lists are mutable, the ``*`` operator (as above) will create a list
 +of N references to the `same` list, which is not likely what you want.
 +Instead, use a list comprehension:
 +
 +.. code-block:: python
 +
 +    four_lists = [[] for _ in xrange(4)]
  
 -Idiomatic Python code is often referred to as being *pythonic*.
  
+ A common idiom for creating strings is to use `join <http://docs.python.org/library/string.html#string.join>`_ on an empty string.::
+     letters = ['s', 'p', 'a', 'm']
+     word = ''.join(letters)
+ This will set the value of the variable *word* to 'spam'. This idiom can be applied to lists and tuples.
+ Sometimes we need to search through a collection of things. Let's look at two options: lists and dictionaries.
+ Take the following code for example::
+     
+     d = {'s': [], 'p': [], 'a': [], 'm': []}
+     l = ['s', 'p', 'a', 'm']
+     
+     def lookup_dict(d):
+         return 's' in d
+     def lookup_list(l):
+         return 's' in l
+ Even though both functions look identical, because *lookup_dict* is utilizing the fact that dictionaries in python are hashtables, the lookup performance between the two is very different.
+ Python will have to go through each item in the list to find a matching case, which is time consuming. By analysing the hash of the dictionary finding keys in the dict can be done very quickly.
+ For more information see this `StackOverflow <http://stackoverflow.com/questions/513882/python-list-vs-dict-for-look-up-table>`_ page.
  
  Zen of Python
  -------------