Python

From Ggl's wiki

Jump to: navigation, search

Some selected pieces from python.org PEPS.

Contents

The Zen of Python

  • Beautiful is better than ugly.
  • Explicit is better than implicit.
  • Simple is better than complex.
  • Complex is better than complicated.
  • Flat is better than nested.
  • Sparse is better than dense.
  • Readability counts.
  • Special cases aren't special enough to break the rules.
  • Although practicality beats purity.
  • Errors should never pass silently.
  • Unless explicitly silenced.
  • In the face of ambiguity, refuse the temptation to guess.
  • There should be one-- and preferably only one --obvious way to do it.
  • Although that way may not be obvious at first unless you're Dutch.
  • Now is better than never.
  • Although never is often better than *right* now.
  • If the implementation is hard to explain, it's a bad idea.
  • If the implementation is easy to explain, it may be a good idea.
  • Namespaces are one honking great idea -- let's do more of those!

Style Guide

Summary of Style Guide for Python Code

Code is read much more often that it is writeen.

  • Indentation: 4 spaces per indentation levels (never mix tabs and spaces, and prefer spaces only).
  • max lines length = 79 lines, and 72 lines for flowing long blocks of text (docstrings or comments). Break a line with implied line continuation inside parentheses or '\'
  • Separate top-level function and class definitions with two blank lines
  • Method definitions inside a class are separated by a single blank line
  • Python 2.x -> Latin-1 (ISO-8859-1) encoding. Python 3.0 -> UTF-8
  • Imports should be on separate lines
  • Imports are always put at the top of the file in the following order:
  1. Standard library imports
  2. Related third party imports
  3. Local application/library specific imports
  • Each group of imports is separated by a blank line
  • spaces:
spam(ham[1], {eggs: 2})
if x == 4: print x, y; y = y, x
  • no spaces around the '=' sign when used to indicate a keyword argument or a default parameter value:
def complex(real, imag=0.0)
  return magic(r=real, i=imag)
  • Write docstrings for all public modules, functions, classes, and methods. Comment should apear after the "def" line.

Naming Conventions

  • _single_leading_underscore: weak "internal use" indicator ("from M import *" does not import objects whose name starts with an underscore).
  • single_trailing_underscore_: used by convention to avoid conflicts with Python keyword
  • __double_lkeading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo)
  • __double_leading_and_traling_underscore__: "magic" objects or attributes that live in user-controlled namespaces. Never invent such names! Only use them as documented.
  • Class: CapWords convention
  • Exception: class naming convention with the suffix "Error"
  • Global Variable: __var__
  • Function: lowercase with words separated by underscores.
  • Function and method arguments:
    • Always use 'self' for the first argument to instance methods.
    • Always use 'cls' for the first argument to class methods.

Programming recommendations

  • Code should be written in a way that does not disadvantage other implementations of Python. Example: use .join() instead of a += b
  • Comparisons to singletons like None should always be done with 'is' or 'is not', never the equality operators.
  • Use class-based exceptions
  • When raising an exception, use "raise ValueError('message')" insted of the older form "raise Valueerror, 'message'"
  • Wen catching exceptions, mention specific exceptions whenever possible instead of using a bare 'except:' clause.
  • For all try/except clauses, limit the 'try' clause to the absolute minimum amount of code necessary. This avoid masking bugs.
  • Use string methods instead of the string module
  • Use .startswith() and endswith() insted of string slicing to check for prefixes or suffixes.
Yes: if foo.startswith('bar'):
No: if foo[:3] == 'bar':
  • Object type comparisons should always use isinstance() instead of comparing types directly.
Yes: if isinstance(obj, int):
No: if type(obj) is type(1):
  • For sequences, (strings, lists, tuples), use the fact that empty sequences are false.
  • Don't compare boolean values to True or False using '=='

Optimization

Excerpt from Python Patterns - An Optimization Anecdote

If you feel the need for speed, go for built-in functions - you can't beat a loop written in C. Check the library manual for a built-in function that does what you want. If there isn't one, here are some guidelines for loop optimization:

  • Rule number one: only optimize when there is a proven speed bottleneck. Only optimize the innermost loop. (This rule is independent of Python, but it doesn't hurt repeating it, since it can save a lot of work. :-)
  • Small is beautiful. Given Python's hefty charges for bytecode instructions and variable look-up, it rarely pays off to add extra tests to save a little bit of work.
  • Use intrinsic operations. An implied loop in map() is faster than an explicit for loop; a while loop with an explicit loop counter is even slower.
  • Avoid calling functions written in Python in your inner loop. This includes lambdas. In-lining the inner loop can save a lot of time.
  • Local variables are faster than globals; if you use a global constant in a loop, copy it to a local variable before the loop. And in Python, function names (global or built-in) are also global constants!
  • Try to use map(), filter() or reduce() to replace an explicit for loop, but only if you can use a built-in function: map with a built-in function beats for loop, but a for loop with in-line code beats map with a lambda function!
  • Check your algorithms for quadratic behavior. But notice that a more complex algorithm only pays off for large N - for small N, the complexity doesn't pay off. In our case, 256 turned out to be small enough that the simpler version was still a tad faster. Your mileage may vary - this is worth investigating.
  • And last but not least: collect data. Python's excellent profile module can quickly show the bottleneck in your code. if you're considering different versions of an algorithm, test it in a tight loop using the time.clock() function.

Tools

Syntax and Style

PyLint, PyFlakes, PyChecker

Profiling

Notes

SQLAlchemy is the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL.

It provides a full suite of well known enterprise-level persistence patterns, designed for efficient and high-performing database access, adapted into a simple and Pythonic domain language.

IPython offers a combination of convenient shell features, special commands and a history mechanism for both input (command history) and output (results caching, similar to Mathematica). It is intended to be a fully compatible replacement for the standard Python interpreter, while offering vastly improved functionality and flexibility.

Introspection

Call a function from a module by its name:

func = getattr(__import__(__name__), "check_%s" % typekind.lower())

As __import__(name) looks for name in sys.modules (which is a dictionnary), sys.modules[name] can also be used.

Dynamically instantiate a class according to its name:

obj = getattr(__import__(__name__), cls.__name__)()

Twisted

I need to write a simple asynchronous web client. For now all the code is in python. I take the chance to try twisted. A good start is Writing Clients from twisted core documentation.

Personal tools