Compared to languages like Perl, Python has a limited number of control constructs:
if and no
for that iterates over sequences and no
foreach or C-style
while that checks a condition every loop and no
if-elif and no
- there's only one comment construct, the
#, and for every line you can tell if it is commented out or not, without looking at previous lines.
Also, there's nearly one way to indent your source; most cases of creative indentation are syntactically excluded.
This makes parsing a Python source easier for humans.
There are attempts to be minimal-but-complete in built-in types and the standard library.
- for mutable list you use the only built-in
list type; it's O(1) for most operations, and you never have to choose the right implementation,
- for immutable lists, equally, you just use the
- for maps, you use the only built-in
dict which is damn efficient in most cases, no need to ponder which implementation to use.
Python 3 extends this to integers: no matter how big your integer is, you use the same type and never care about coercion.
Python tries to avoid syntactic sugar. But sometimes it adds syntactic sugar just to make the obvious way obvious. You can write
if foo is not None instead of
if not (foo is None) because 'is not' is special-cased. Still
foo is not None reads easily, can't be misinterpreted, and you don't have to think, you just write the obvious thing.
Of course, most of more complex things in Python can be done in several ways. You can add methods to classes by declaration or by simple slot assignment, you can pass arguments to functions in a number of creative ways, etc. That's just because the internals of the language are mostly exposed.
The key is that there's always one way which is intended to be the best, the cover-all case. If other ways exist, they were not added as equal alternatives (like
unless) but merely expose the inner workings. Slowly but steadily such alternatives are obsoleted (not eliminated!) by enhancing the known best mechanism.
Decorators wrap AOP function calls. Before 2.7 you had to use
__metaclass__ magic member to declare a class's metaclass; now you can use the same decorator syntax for this, too. Prior to 3.0 you had two sorts of strings, byte-oriented and Unicode, which you could inadvertently mix. Now you have the only Unicode
str and the only binary-transparent
bytes, which you can't mix by mistake.