diff doc/v2_planning/API_coding_style.txt @ 1150:d7192e52653e

coding_style: Moved some elements to official API
author Olivier Delalleau <delallea@iro>
date Thu, 16 Sep 2010 17:00:58 -0400
parents 2da593b0f29d
children 531e77fb67f2 a0f178bc9052
line wrap: on
line diff
--- a/doc/v2_planning/API_coding_style.txt	Thu Sep 16 16:25:38 2010 -0400
+++ b/doc/v2_planning/API_coding_style.txt	Thu Sep 16 17:00:58 2010 -0400
@@ -7,7 +7,7 @@
 
     * Code should be compatible with Python 2.4 and above (using 2to3 for
       conversion to Python 3.x). This may not be possible in the short term
-      for code dependent on Theano.
+      for Theano-dependent code.
 
     * Code should be easy to read, understand and update by developers and
       users.
@@ -23,7 +23,7 @@
 Source Material
 ~~~~~~~~~~~~~~~
 
-The three main documents describing our Python coding guidelines are:
+The four main documents describing our Python coding guidelines are:
     * `PEP 8 -- Style Guide for Python Code
       <http://www.python.org/dev/peps/pep-0008>`_
     * `PEP 257 -- Docstring Conventions
@@ -39,12 +39,100 @@
 
     * Use only one space (not two) after a sentence-ending period in comments.
 
+    * You do not need to add an extra blank line before the closing quotes of
+      a multi-line docstring.
+
+      .. code-block:: python
+
+        # Good.
+        """This is a multi-line docstring.
+
+        Which means it has more than one line.
+        """
+
+        # Bad.
+        """This is a multi-line docstring.
+
+        Which means it has more than one line.
+
+        """
+
 Excerpts
 ~~~~~~~~
 
 We emphasize here a few important topics that are found in the official
 guidelines:
 
+    * Avoid using lists if all you care about is iterating on something. Using
+      lists:
+        - uses more memory (and possibly more CPU if the code may break out of
+          the iteration),
+        - can lead to ugly code when converted to Python 3 with 2to3,
+        - can have a different behavior if evaluating elements in the list has
+          side effects (if you want these side effects, make it explicit by
+          assigning the list to some variable before iterating on it).
+
+      +------------------------+------------------------+
+      | Iterative version      |    List version        |
+      +========================+========================+
+      | .. code-block:: python | .. code-block:: python |
+      |                        |                        |
+      |   my_dict.iterkeys     |   my_dict.keys         |
+      |   my_dict.itervalues   |   my_dict.values       |
+      |   my_dict.iteritems    |   my_dict.items        |
+      +------------------------+------------------------+
+      | .. code-block:: python | .. code-block:: python |
+      |                        |                        |
+      |   itertools.ifilter    |   filter               |
+      |   itertools.imap       |   map                  |
+      |   itertools.izip       |   zip                  |
+      +------------------------+------------------------+
+      | .. code-block:: python | .. code-block:: python |
+      |                        |                        |
+      |   xrange               |   range                |
+      +------------------------+------------------------+
+
+      Code example with ``map``:
+
+      .. code-block:: python
+
+        # Good.
+        for f_x in imap(f, x):
+            ...
+        all_f_x = map(f, x)
+        map(f, x)
+        # Bad.
+        for element in map(f, x):
+            ...
+        imap(f, x)
+
+    * Generally prefer list comprehensions to ``map`` / ``filter``, as the former are
+      easier to read.
+
+      .. code-block:: python
+
+        # Good.
+        non_comments = [line.strip() for line in my_file.readlines()
+                                     if not line.startswith('#')]
+        # Bad.
+        non_comments = map(str.strip,
+                           ifilter(lambda line: not line.startswith('#'),
+                                   my_file.readlines()))
+ 
+    * Use ``in`` on container objects instead of using class-specific methods:
+      it is easier to read and may allow you to re-use your code with different
+      container types.
+
+      .. code-block:: python
+
+        # Good.
+        has_key = key in my_dict
+        has_substring = substring in my_string
+        # Bad.
+        has_key = my_dict.has_key(key)
+        has_substring = my_string.find(substring) >= 0
+
+
 Additional Recommendations
 --------------------------
 
@@ -76,13 +164,14 @@
       .. code-block:: python
 
         # Good.
-        for my_very_long_variable_name in [my_food, my_bar, my_love,
+        for my_very_long_variable_name in [my_foo, my_bar, my_love,
                                            my_everything]:
             ...
         for my_very_long_variable_name in [
                 my_foo, my_bar, my_love, my_everything]:
             ...
-        # Good iff the list needs to be frequently updated.
+        # Good iff the list needs to be frequently updated or is easier to
+        # understand when each element is on its own line.
         for my_very_long_variable_name in [
                 my_foo,
                 my_bar,
@@ -90,6 +179,10 @@
                 my_everything,
                 ]:
             ...
+        # Good as long as it does not require more than two lines.
+        for my_very_long_variable_name in [my_foo,
+                                           my_bar]:
+            ...
         # Bad.
         for my_very_long_variable_name in [my_foo, my_bar, my_love,
                 my_everything]:
@@ -100,6 +193,7 @@
                                            my_everything]:
             ...
 
+
 The ``logging`` Module vs. the ``warning`` Module
 =================================================