Compared to languages like Perl, Python has a limited number of control constructs:
- only
if
and no unless
,
- only
for
that iterates over sequences and no foreach
or C-style for
,
- only
while
that checks a condition every loop and no do-while
,
- only
if-elif
and no switch
,
- 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
tuple
type,
- 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 if
and 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.6 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.