Learning Python

Kent Borg kentborg-KwkGvOEf1og at public.gmane.org
Thu Jun 25 15:00:42 EDT 2009


Earlier I wrote:
> Something I have not found is the right whack in the head to get one to
> think in pythonic terms and not program like a C programmer.  Fully
> grokking "list comprehensions" seems a start, but I am thinking I need a
> journal article length piece to reread every while until it sinks in.

So I did some looking around and found several things that might be useful:

1. "What is Pythonic"
http://faassen.n--tree.net/blog/view/weblog/2005/08/06/0

It isn't deep, but if gives some nice examples of how to do things in C,
how that translates directly into Python, and then the right way to do
it in Python.


2. "Be Pythonic" http://shalabh.infogami.com/Be_Pythonic2

A bit longer, but still only 6 simple assertions with elaboration and
examples. It has more depth than is immediately apparent and is worth
rereading later.


3. "How to Write 'Pythonic' Code"
http://www.chrisarndt.de/talks/rupy/2008/output/slides.html#list-comprehensions

Much longer than the first two suggestions, has some profound bits, has
lots of examples worth mulling over and rereading later.


4. "Pythonic Defined"
http://techblog.ironfroggy.com/2007/06/pythonic-defined.html

More haphazard than the others but some good bits. Includes a very short
summary of standard Python coding style.



Because I have been thinking about it, here are some of my thoughts on
the key aspects of Python for a C person:

- Blocks are indicated by indentation not by start and end tokens.

- Python is interpreted. Actually the ASCII is compiled into bytecodes
(automagically: write a foo.py file and a foo.pyc fill will appear once
you run it). The bytecodes are interpreted.

- Variables are not declared, they are just used. They can be local or
global.

- Parameters can be positional (like C) but they can also be named, and
they can be missing and have default values.

- Instead of "#include" Python uses "import". Imports are close to being
a lexical insert, but can preserve distinctive name spaces ("import
os"), or be flat ("from os import *"), or mangle name spaces ("import os
as foo"). Because python is interpreted, the importing has immediate
effect--in that sense it is like a library linkage step in C.

- Everything is an object and objects are strongly typed. A variable,
however, is not typed and it can point to any kind of object. Runtime
enforcement is duck typing: 'I need it to quack, and to walk, if it can
do that, it is duck enough for me'.

- Late binding. Python won't know what type an object is until it sees
it at runtime. Object and class definitions can be messed with at
runtime, too.

- Dynamic. Stuff will pop into existence without explicit malloc-like
calls, and things that are no longer needed will disappear without any
explicit freeing.

- The key data structure is a list (of any data types, including other
lists). If you have more than one of something, put them in a list.
Lists are ordered and mutable: you can add things and remove things, you
can access by index, you can mangle based on an index range. Where in C
you would write "for (i=0; i<n; i++) ..." in Python use a list, possibly
do: "for my_item in some_list: ...". Assigning a list to a variable is
effectively taking its address, assign it to another variable and the
two variables point to the same data. Pass a list as a parameter and it
is efficiently passed by reference.

- A "list comprehension" is a for-loop style syntax to describe a list.
It is a far better choice than manually assembling your list in a for-loop.

- If you have too many of something to instantiate it all in a list,
don't--but pretend that you did! Use an iterator, xrange, generator,
etc. Things that respond to key methods of a list, without all that
enumerating.

- A "generator expression" is very much like a list comprehension but it
doesn't build the whole list in memory.

- Python is efficient when the underlying grunt work is implemented in
C. If you are sifting through a lot of bits in high level code, look for
a way to hand that off to some existing library. (The data you will hand
off will likely be a list--or somewhat like a list.)

- Python can be extended in C, but it is a pain. Consider using pyrex to
glue together C and Python.

- There is no C-like optimizer in Python, instead figure out how to hand
your data to existing libraries. Or, to put it another way: Don't worry
about factoring common code out of your inner loop, instead figure out
how to not write the inner loop.

- Python is procedural, but try to think in functional terms and you
might get faster code.

- Python loves tuples, they are immutable, use them for heterogeneous
data ("(length, width, depth)"), they can be returned from functions,
you can assign a slew of things at once via a tuple. A swap would be "a,
b = b, a". The key syntax for a tuple is actually the comma, though
frequently it seems like it is parentheses.

- Python has a neat hash table built-in called dictionaries. Don't over
use them. Think in lists and tuples first.

- Python strings are immutable, so appending a character to a string
makes an entirely new string. Remember that before designing your
involved string algorithm.

- Python does not include regular expressions in the language, but there
are some useful string methods that might save you from having to figure
out the regular expression library.

- Instance variables are object attributes ("my_obj.my_attrib = 42").
Classes can also have attributes. There are methods you can implement to
make getter or setter bottlenecks.

- Python does threads, but they all run inside a single threaded
interpreter (and so run on a single CPU) and there is global interpreter
lock that can starve other threads. (If you really want a lot of
threads, checkout the language Erlang...)

- Python is currently at version 2.6.2, it is better than earlier
versions, great effort has been made to maintain backwards
compatibility, so later versions are better. The "other current version"
is 3.0.1, it is largely the same as 2.6, but it has made some
incompatible changes. Everyone seems to agree 3.0 is an improvement, but
breaking backward compatibility makes this a bleeding edge choice. There
is a dumb utility called 2to3 that will do the mechanical updating of
2.x code, but a programmer will still need to port unfortunate things.
Not all libraries have been ported to 3.0. It is possible to develop
entirely under 2.6, but in a 3.0 compatible mode, depending on 2to3 as a
build tool to produce 3.0 output, making a final jump to 3.0 as easy as
using the 2to3 output as your new source code.


-kb






More information about the Discuss mailing list