Mercurial > pylearn
diff doc/v2_planning/API_coding_style.txt @ 1159:531e77fb67f2
coding_style: Moved more elements to official 'API'
author | Olivier Delalleau <delallea@iro> |
---|---|
date | Fri, 17 Sep 2010 12:05:14 -0400 |
parents | d7192e52653e |
children | 4f1b9e0a1377 |
line wrap: on
line diff
--- a/doc/v2_planning/API_coding_style.txt Fri Sep 17 11:21:15 2010 -0400 +++ b/doc/v2_planning/API_coding_style.txt Fri Sep 17 12:05:14 2010 -0400 @@ -63,14 +63,35 @@ We emphasize here a few important topics that are found in the official guidelines: + * Only use ASCII characters in code files. + + * Code indent must be done with four blank characters (no tabs). + + * Limit lines to 79 characters. + + * Naming conventions: ``ClassName``, ``TOP_LEVEL_CONSTANT``, + ``everything_else``. + + * Comments should start with a capital letter (unless the first word is a + code identifier) and end with a period (short inline comments may skip + the period at the end). + + * Imports should be listed in alphabetical order. It makes it easier to + verify that something is imported, and avoids duplicated imports. + + * Use absolute imports only. This is compatible across a wider range of + Python versions, and avoids confusion about what is being + imported. + * 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). + + - 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 | @@ -100,7 +121,7 @@ for f_x in imap(f, x): ... all_f_x = map(f, x) - map(f, x) + map(f, x) # f has some side effect. # Bad. for element in map(f, x): ... @@ -132,12 +153,89 @@ has_key = my_dict.has_key(key) has_substring = my_string.find(substring) >= 0 + * Do not use mutable arguments as default values. Instead, use a helper + function (conditional expressions are forbidden at this point, see + below). + + .. code-block:: python + + # Good. + def f(array=None): + array = pylearn.if_none(array, []) + ... + # Bad. + def f(array=[]): # Dangerous if `array` is modified down the road. + ... + + * Use a leading underscore '_' in names of internal attributes / methods, + but avoid the double underscore '__' unless you know what you are + doing. + Additional Recommendations -------------------------- Things you should do even if they are not listed in official guidelines: + * No conditional expression (not supported in Python 2.4). These are + expressions of the form ``x = y if condition else z``. + + * Use ``//`` for integer division and ``/ float(...)`` if you want the + floating point operation (for readability and compatibility across all + versions of Python). + + .. code-block:: python + + # Good. + n_samples_per_split = n_samples // n_splits + mean_x = sum(x) / float(len(x)) + # Bad. + n_samples_per_split = n_samples / n_splits + mean_x = sum(x) / len(x) + + * Always raise an exception with ``raise MyException(args)`` where ``MyException`` + inherits from ``Exception``. This is required for compatibility across + all versions of Python. + + .. code-block:: python + + # Good. + raise NotImplementedError('The Pylearn team is too lazy.') + # Bad. + raise NotImplementedError, 'The Pylearn team is too lazy.' + raise 'The Pylearn team is too lazy to implement this.' + + * Use either ``try ... except`` or ``try ... finally``, but do not mix + ``except`` with ``finally`` (which is not supported in Python 2.4). + You can however embed one into the other to mimic the ``try ... except ... + finally`` behavior. + + .. code-block:: python + + # Good. + try: + try: + something_that_may_fail() + except SomeError: + do_something_if_it_failed() + finally: + always_do_this_regardless_of_what_happened() + # Bad. + try: + something_that_may_fail() + except SomeError: + do_something_if_it_failed() + finally: + always_do_this_regardless_of_what_happened() + + * Do not use the ``all`` and ``any`` builtin functions (they are not supported + in Python 2.4). Instead, import them from ``theano.gof.python25`` (or + use ``numpy.all`` / ``numpy.any`` for array data). + + * Do not use the ``hashlib`` module (not supported in Python 2.4). We will + probably provide a wrapper around it to be compatible with all Python + versions. + * Avoid backslashes whenever possible. They make it more difficult to edit code, and they are ugly (as well as potentially dangerous if there are trailing white spaces). @@ -193,6 +291,50 @@ my_everything]: ... + * Use the ``key`` argument instead of ``cmp`` when sorting (for Python 3 + compatibility). + + .. code-block:: python + + # Good. + my_list.sort(key=abs) + # Bad. + my_list.sort(cmp=lambda x, y: cmp(abs(x), abs(y))) + + * Whenever you read / write binary files, specify it in the mode ('rb' for + reading, 'wb' for writing). This is important for cross-platform and + Python 3 compatibility (e.g. when pickling / unpickling objects). + + .. code-block:: python + + # Good. + cPickle.dump(obj, open('my_obj.pkl', 'wb', protocol=-1)) + # Bad. + cPickle.dump(obj, open('my_obj.pkl', 'w', protocol=-1)) + + * Avoid tuple parameter unpacking as it can lead to very ugly code when + converting to Python 3. + + .. code-block:: python + + # Good. + def f(x, y_z): + y, z = y_z + ... + # Bad. + def f(x, (y, z)): + ... + + * Only use ``cPickle``, not ``pickle`` (except for debugging purpose since + error messages from ``pickle`` are sometimes easier to understand). + + * A script's only top-level code should be something like: + + .. code-block:: python + + if __name__ == '__main__': + sys.exit(main()) + The ``logging`` Module vs. the ``warning`` Module =================================================