tags:

views:

4164

answers:

17
+43  Q: 

zen of python

There is the Zen of Python written by Tim Peters. It is considered like a summary manual of python's philosophy. Here it is:

>>> import this

The Zen of Python, by Tim Peters

  • 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!

Can I have an example of each of those items, applied to real python programming?

I think one example per answer would be best, so we could vote on each example.

Also, examples mixing languages may be cool, but it would be best to have also python-only examples, showing the wrong and the right way of doing something.

+15  A: 

I can give an example of "readability counts" (the easy one :D) Compare C and Python:

 #include <stdio.h>
 int main(void) {
     printf("Hello, world!\n");
     return(0);
 }
print "Hello, world!"

(And what about indentation? Well-indented code is more readable. Thus, in Python it's mandatory)

Federico Ramponi
Cool, but I'd like to see python examples instead.
nosklo
Or even worsestd::cout << "Hello World" << std:endl;
Martin Beckett
I don't think this is entirely valid, since that code is "readable" c code. A more suitable example would be an unreadable python vs readable python.
freespace
Agreed, that's just the basic structure to set up a C program. It's perfectly readable.
Bob Somers
I don't think that the "zen of python" is a list of best practices in python. According to me it's an explanation of why Python is as we know it, why was it designed to be so. Thus, I think comparisons with other languages are useful...
Federico Ramponi
@Bob, I disagree -- to someone who knows neither language, the C is *less* readable.
Charles Duffy
I agree with @Federic Ramponi; I understand that this koan means "Python should be readable compared with other languages". At PyCon, I recall hearing Guido say that it should look like English.
S.Lott
A: 

Not an appropriate question for this site. Besides, a lot of these don't even apply to python or are so generic they convey nothing.

Christopher
How is it inappropriate? Have you read the site FAQ?Your answer is inappropriate instead. You should use a comment or just plain downvoting instead of an answer for your comment.
nosklo
+18  A: 

There should be one - and preferably only one - obvious way to do it. (The exact contrary of perl's motto - there's more than one way to do it).

How many ways could you provide to "iterate over a sequence" in C++? Iterating over an array with integers or pointers; iterating over STL vectors with various kinds of iterators... etc. If you want to be proficient in C++ (and be able to read other people's code), you must learn them all. In Python you must learn only one:

for element in sequence:

And isn't it obvious?

This is also why they're dropping duplicate modules in Python3000's standard library. There should be one module for every need.

[Although that way may not be obvious at first unless you're Dutch: OK, Guido van Rossum is Dutch].

Federico Ramponi
You've forgotten a `while` loop. It is almost never used to iterate over a sequence but it can be done with it.
J.F. Sebastian
It's not 100% true, u know, somethings can be done with either for loops or list comprehensions or a combination of map/filter (or even a plain old while loop)
hasen j
Yet there are zillion ways to do things in the Python packaging world.
Sridhar Ratnakumar
There are multiple ways to do it, but the most of them are just wrong or doesn't make any sense in some situations. It's a convention to use a specific solution to a specific problem. Also the Zen of Python are more a philosophy of coding, that a static dogma.
Joschua
+8  A: 

I'll try to tackle

Errors should never pass silently. Unless explicitly silenced.

This could be a reference to the warnings module and the -W option on the command line.

Default -- show once.

>>> import warnings
>>> warnings.warn( "Not good" )
__main__:1: UserWarning: Not good
>>> warnings.warn( "Not good" )
>>>

Here's a programmatic explicit silencing.

>>> warnings.simplefilter("ignore",Warning)
>>> warnings.warn( "Not good" )
>>>

You can also use the -W command-line option to silence warnings. For example -Wi will ignore all warnings.

Nothing is simpler than just including warnings wherever you think they might be helpful for troubleshooting, knowing that warning management and logging is already written.

S.Lott
Man. I didn't even know about the warnings module. Good stuff.
crystalattice
Could be a reference to exceptions, and things like not doing `try: ...; except: pass`
dbr
+18  A: 

Explicit is better than implicit.

That's why you should never do anything like this:

from os import *
print getcwd()

Instead, every time you invoke a function you should name its module explicitly:

import os
print os.getcwd()

In case you forget this best practice, let the last koan remind it to you: Namespaces are one honking great idea - let's do more of those!

Another example: the 'self' parameter in methods. You always have to mention explicitly what object you are working with.

Federico Ramponi
Why do so many examples start off with the `from x import *` idiom? It might be fine for production code, but not for people trying to learn your library or framework!
David Eyk
It isn't even fine for production code. I vastly prefer either explicitly importing exactly those names you need, or explicitly naming the module each time.
Omnifarious
Or, if you don't like typing lots of code, `import biglonghugename as bname` (the main one I use is `import Tkinter as tk`)
Wayne Werner
+27  A: 

Special cases aren't special enough to break the rules.

A string of length 1 is not special enough to deserve a dedicated char type.

Although practicality beats purity.

That's why we have the chr() and ord() builtins.

Federico Ramponi
Not a python guy but i like that first item :)
RCIX
A: 

This will probably be downvoted, but take a look at 99 Bottles of Beer. It has multiple examples of different programming languages printing the "99 bottles of beer" song.

I'm actually using several examples in the Python book I'm writing to showcase why Python is a great language to learn. The simplicity and elegance of Python is a stark contrast to the convoluted code some people have created, and that's not counting the deliberate obfuscated code.

crystalattice
Look at that. I got downvoted.
crystalattice
maybe self fulfilling prophecy! I was about to downvote this just because you said "this will probably be downvoted"
hasen j
Or maybe it got downvoted because it doesn't answer the question. ;)
Xiong Chiamiov
+8  A: 

Although the poem predates this, here's my take on

Although that way may not be obvious at first unless you're Dutch.

The classic trinary if-then-else operator (it's cond?expr1:expr2 in C) was debated hotly. Guido came up with this

a = expr1 if cond else expr2

This is the one way to do this, and it isn't obvious at first. One of the sidebars for this is always the observation that the condition is evaluated first irrespective of the left-to-right order of the operands.

There's actually a precedent for this in some work (I think) by Hoare or Wirth on algebraic analysis of algorithms. Their article pitched this simplified if structure so you could just write the decisions out as a simple expression with an obvious effect.

S.Lott
Is there really only one way to do it though ? how about a = cond and expr1 or expr2 ?
Thomas Vander Stichele
The "cond and expr1 or expr2" -- while provably the same -- is deprecated because it's hard to manage the operator priority issues when the condition is non-trivial. You either have to parenthesize everything or do a lot of thinking. :-(
S.Lott
Also, there may be issues if expr1 can be false :|
Federico Ramponi
+10  A: 

The module this itself is an example of what you don't have to do, it has implicit behaviour, ambiguity, complexity, unreadability... a pure gem :)

import this

dir(this)

this.c
this.d
this.i
this.s

"".join([c in this.d and this.d[c] or c for c in this.s])

help(this)
Jaime Soriano
yeah, this is an example how it looks, when not using the Zen of Python! :D
Joschua
+7  A: 

One more: "Flat is better than nested."

I think this is the Pythonic style of piling a bunch of class definitions and singleton object creations into a single module file.

In other languages (particularly C++ or Java where the expectation is one class per file) there would be a whole directory full of files. With Python, it's a single file and that's that. Much of the library follows this "Flat is better than nested" style.

Also, the definitions of the built-in types looks relatively flat. Compare it with the Java collection classes or the C++ STL; both have considerable depth to the class inheritance, making it harder to comprehend.

S.Lott
+11  A: 

Errors should never pass silently.

try:
    import this
except ImportError:
    print 'this is not available'

Unless explicitly silenced.

try:
    v = d[k]
except KeyError:
    v = d[k] = default
Ali A
Of course, you could just use d.setdefault(). ;)
Benjamin Peterson
or `collections.defaultdict`
J.F. Sebastian
+16  A: 

"Beautiful is better than ugly."

Behold, Euler's Algorithm to find the greatest common denominator in 4 lines:

def gcd(x, y):
    while y:
        x, y = y, x % y
    return x

Of course, the mathematical beauty comes from the algorithm, but I love the way Python succeeds at being precise, concise, and explicit at the same time. In fact "elegant" also comes to mind. Of course, any language that can implement qsort in only one more line than C's "Hello World" certainly has a claim on elegance.

J.T. Hurley
In c hello world is is 4 lines. #include <stdio.h> int main(void) { printf("Hello, world!\n"); return(0); }I would love to see a 5 line quicksort.
uswaretech
Here is a Python one line, one statement lambda quicksort: qsort1 = lambda lst : lst if len(lst) <= 1 else qsort1([i for i in lst[1:] if i < lst[0]]) + [lst[0]] + qsort1([i for i in lst[1:] if i >= lst[0]])
truppo
+5  A: 

Namespaces are one honking great idea -- let's do more of those!

When you import modules, like

# import everything from a module
import module
# call some function in the module
module.spam()

# import some class from module
import module
breakfast = module.SpamAndEggs()

they are not added to the global namespace. Unless you write:

from module import *

Which you should never do, except maybe for convenience when testing things in the command prompt. Imported modules get their own namespace, which you refer to with the module name like in the first example above. This is good because there is less risk of name conflicts.

If you have some module or class with a long name, import them with aliasing:

# long module name
import aRidiculouslyLongModuleName as short
# long class name
from aRidiculouslyLongModuleName import RatherLongClassName as ShortClass
Johan
+5  A: 

Sparse is better than dense

if i>0: return sqrt(i)
elif i==0: return 0
else: return 1j * sqrt(-i)

versus

if i > 0:
    return sqrt(i)
elif i == 0:
    return 0
else:
    return 1j * sqrt(-i)

To rephrase the dictum another way, "Don't try to stick too much code on one line."

Quoting (with added sparseness) python-list.

ddaa
+2  A: 

In the face of ambiguity, refuse the temptation to guess

Consider:

if not a and b:
   assert not a
   assert b

What binds more tightly 'not' or 'and'? The syntax is unambiguous but my memory is not.

Could it be? (no):

if not (a and b):
   pass

If short-circuiting doesn't matter then I'd write it:

if b and not a:
   pass

Or somewhat ugly but reliable if it does:

if (not a) and b:
   pass

This is subjective because someone may argue that you should expect the reader of your code to know Python and thus the priorities for 'not' and 'and', and it is not obscure enough to justify parentheses.

J.F. Sebastian
A: 

Here's another example of

Explicit is better than implicit.

, applied to the language itself.

While Python is dynamically-typed, it is also strongly-typed. Several scripting languages allow things like this:

<?php
$foo = "5";
echo $foo * 3;
?>

[$]> php test.php 
15%

(The % is a result of me not adding a newline to the end of the echo statement.)

This is known as type coercion. You'll also see it used frequently in C, where programmers often take advantage of the compiler's lack of caring to put bits in places they don't belong (as viewed by someone like me :) ).

Now, in Python, multiplying a string by an integer will print the string that many times:

>>> foo = "5"
>>> foo * 3
'555'

because Guido decided to override that particular operator. Adding them, however,

>>> foo+3
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

produces an exception. If you really want to do so, then you need to tell Python that, dammit, you want an integer.

>>> int(foo)+3
8
Xiong Chiamiov
A: 

Although that way may not be obvious at first unless you're Dutch

...or ','.join(nationalities.pop('Dutch')). inferred from:

Special cases aren't special enough to break the rules