In [ ]:
import this
Consider the following two possible ways of writing the same code, and consider which
one looks more beautiful.
The second example reads a bit more like natural English, and explicitly including the name of the
argument gives greater insight into its purpose.
is_valid = form != null && form.is_valid(true)
is_valid = form is not None and form.is_valid(include_hidden_fields=True)
Python asks you to declare your intentions explicitly, rather than issue every command necessary to make that intention a reality. For example, when assigning a value to a variable, you don’t need to worry about setting aside the necessary memory, assigning a pointer to the value and cleaning up the memory once it’s no longer in use. Memory management is a necessary part of variable assignment, so Python takes care of it behind the scenes. Assigning the value is enough of an explicit declaration of intent to justify the implicit behavior.
The following two lines of code are functionally identical for strings, but notice the difference in complexity between them.
As you can see, the second option is much simpler to read and understand.
if value is not None and value != '':
if value:
Complex — Made up of many interconnected parts. Complicated — So complex as to be difficult to understand.
The goal is to keep things as relationships of peers as much possible,
rather than parents and children. For example, take the following code snippet, which illustrates the
problem.
In this example, it’s fairly difficult to follow what’s really going on because the nested nature of the code
blocks requires you to keep track of multiple levels of conditions. Consider the following alternative
approach to writing the same code, flattening it out.
if x > 0:
if y > 100:
raise ValueError("Value for y is too large.")
else:
return y
else:
if x == 0:
return False
else:
raise ValueError("Value for x cannot be negative.")
if x > 0 and y > 100:
raise ValueError("Value for y is too large.")
elif x > 0:
return y
elif x == 0:
return False
else:
raise ValueError("Value for x cannot be negative.")
The goal is to keep highly related snippets together, while separating them from subsequent or unrelated code, rather than simply having everything run together in an effort to save a few bytes on disk.
Yes: spam(ham[1], {eggs: 2})
No: spam( ham[ 1 ], { eggs: 2 } )
Yes: if x == 4: print x, y; x, y = y, x No: if x == 4 : print x , y ; x , y = y , x
Yes: spam(1) No: spam (1)
Yes: dict['key'] = list[index] No: dict ['key'] = list [index] </pre></code>
If you’re committed to backward compatibility, internationalization, readability or anything else, don’t break those promises just because a new feature comes along and makes some things a bit easier.
Take the following simple Python function and look for
any promises that can be broken.
def validate(data):
if data['username'].startswith('_'):
raise ValueError("Username must not begin with an underscore.")
In the preceding validation example, it’s likely that the
validation errors should be shown to the user in a nicer way than a full traceback.
import sys
def validate(data):
if 'username' in data and data['username'].startswith('_'):
raise ValueError("Username must not begin with an underscore.")
if name == 'main': username = sys.argv[1] try: validate({'username': username}) except TypeError, ValueError as e: print e </pre></code>
This is a nod to the homeland of Python’s creator and Benevolent Dictator for Life, Guido van Rossum.