Abstract:
You should choose between Python 2 and 3, find a good book, and keep in mind the diverse data types.

Created by Peter Kankowski
Last changed
Filed under Interpreters and compilers

Share on social sitesReddit Digg Delicious Buzz Facebook Twitter

Python critique

Python is a great programming language, elegant and concise. However, it has flaws and shortcomings. Here are some of them.

Version hell

Python 3 is backwards imcompatible with Python 2. Though the former was released almost two years ago, popular libraries and web hostings still support only Python 2.x. Google AppEngine uses Python 2.5, which has a very different syntax from Python 3. Django works on Python 2.7, but not on Python 3. And so on.

# Python 2.5                    # Python 3
for i in xrange(9):             for i in range(9):
    print '%02d' % (i / 3),         print( '{:02d}'.format(i // 3), end=' ' )

# Differences:
#   no xrange (range must be used instead),
#   print is a function,
#   format should be used instead of %,
#   integer division is now //, not /

If you want to write a script or a web app, you have to choose between the versions. Python 2.x is supported everywhere, but you will have to rewrite your code in future. Python 3 is for "brand new things", as van Rossum says, but it still has little support, so you will be limited in the choice of hosting provider for your web app.

Side-by-side installation of Python 2 and 3 under Windows is problematic. It would be much easier if Python 3 scripts had a different file extension, for example, py3 instead of py.

Incomprehensible language reference

Python language reference sounds like the author wrote it for himself. It's hardly usable for an average Python developer. Compare:

PythonPHP
String literals are described by the following lexical definitions:
stringliteral   ::=  [stringprefix](shortstring | longstring)
stringprefix    ::=  "r" | "R"
shortstring     ::=  "'" shortstringitem* "'" |
                     '"' shortstringitem* '"'
longstring      ::=  "'''" longstringitem* "'''" |
                     '"""' longstringitem* '"""'
shortstringitem ::=  shortstringchar | stringescapeseq
longstringitem  ::=  longstringchar | stringescapeseq
shortstringchar ::=  <any source character except "\"
                     or newline or the quote>
longstringchar  ::=  <any source character except "\">
stringescapeseq ::=  "\" <any source character>

...
One syntactic restriction not indicated by these productions is that whitespace is not allowed between the stringprefix or bytesprefix and the rest of the literal...
In plain English: Both types of literals can be enclosed in matching single quotes (') or double quotes ("). They can also be enclosed in matching groups of three single or double quotes (these are generally referred to as triple-quoted strings). The backslash (\) character is used to escape characters that otherwise have a special meaning, such as newline, backslash itself, or the quote character.
The simplest way to specify a string is to enclose it in single quotes (the character ').
To specify a literal single quote, escape it with a backslash (\). To specify a literal backslash, double it (\\). All other instances of backslash will be treated as a literal backslash: this means that the other escape sequences you might be used to, such as \r or \n, will be output literally as specified rather than having any special meaning.
<?php
echo 'this is a simple string';

echo 'You can also have embedded newlines in 
strings this way as it is
okay to do';

// Outputs: Arnold once said: "I'll be back"
echo 'Arnold once said: "I\'ll be back"';

// Outputs: You deleted C:\*.*?
echo 'You deleted C:\\*.*?';

...

PHP documentation does not try to explain several types of strings (single-quoted and triple-quoted) in one paragraph; it provides examples and skips unreadable "lexical definitions".

When using PHP, you can look up the language reference when you don't remember how an obscure language feature works. When using Python, you have to decipher the grammar reference or try to find it in the tutorial (which does not describe all features).

Optimized data types (immutable, ranges and iterators)

Python has subtle different data types (list and tuple, bytes and bytearray), so you often have to think "Do I need the mutable type here?" Pythonists disagree about the proper usage for tuples.

IMHO, tuple is an optimized particular case of a list. They are faster than usual lists and allow simple hashing, so a tuple can be a dictionary key, but this feature is rarely used. Other programming languages have one data structure where Python has two.

Another "optimized" data type is iterator, a "lazy" data structure. In Python 2, map function returns a list; in Python 3, it returns an iterator object, which behaves like list in some (but not all) aspects. It cannot be printed or indexed without converting to a list. You can pass it to min or max function, but only once, so you cannot find both minimum and maximum without coercion to a list:

a = map(int, '1 2 3'.split())

print(a) # prints: <map object at 0xABCD>, not [1, 2, 3]

a[2] # TypeError: 'map' object is not subscriptable

print( min(a) ) # prints 1

print( max(a) ) # error, because the iterator already was "iterated"

In essence, Python burdens programmer with choosing the fastest data structure. Instead, the interpreter could always use lists. The programmer would not have to focus on the implementation details and remember the peculiar syntax of tuples or the non-intuitive behavior of iterators. A more sophisticated language implementation (such as RPython) could analyze the program and choose the optimized types automatically, without introducing new types to the language.

Conclusion

Python is definitely better planned that other scripting languages, but you should choose between the versions, find a good book, and keep in mind the diverse data types.

Additional reading

Peter Kankowski
Peter Kankowski

About the author

Peter is the developer of Aba Search and Replace, a tool for replacing text in multiple files. He likes to program in C with a bit of C++, also in x86 assembly language, Python, and PHP. He can be reached at kankowski@gmail.com.

Created by Peter Kankowski
Last changed

28 comments

Ten recent comments are shown below. Show all comments

Peter Kankowski,
The tutorial does explains everything about string syntax, escape sequence, etc.

The tutorial does not contain the list of escape sequences. It also does not explain byte literals.

Trying to explain single- and double-quote in two separate paragraphs would make it really redundant...

I wrote "single-quoted and triple-quoted". Triple-quoted strings have different rules for unescaped newlines and quotes.

...however, there is nothing in common between the use case for tuples and lists.

You have to coerce list to tuple when you want to use it as a dictionary key (my two-stage table script contains an example).

Python's tuple is intended to be a lightweight struct.

A list can be easily used for the same purpose. However, a tuple cannot be always used instead of a list. So, from implementation point of view, tuple is an optimized particular case of a list.

There is virtually no difference in the speed of tuple and lists...

According to these benchmarks, constructing a small tuple is ­≈6 times faster than constructing the equivalent list.

Lie,

> It also does not explain byte literals.

Byte literal syntax is new in Python 3.x and as of now not very well-documented anywhere, you're welcome to contribute a documentation if you'd like to.

>> Trying to explain single- and double-quote in two separate paragraphs would make it really redundant...

> I wrote "single-quoted and triple-quoted". Triple-quoted strings have slightly different rules for unescaped newlines and quotes.

You wrote "PHP documentation does not try to explain several types of strings ... in one paragraph"; in the tutorial triple-quoted string is explained five paragraphs below the paragraph explaining single-quoted string. It's true the language reference explains them all in one paragraph, but if you're reading the language reference, you should already be familiar with how the various string literal works and the first paragraph is a mundane item that you'd want to skip through as fast as possible. Again, language reference (of any language) is not a beginner's tutorial; PHP mislabeled their tutorial as a language reference (notably lacking in PHP's "language reference" is a normative, formal description of the string literal syntax).

>> There is virtually no difference in the speed of tuple and lists...

> According to these benchmarks, constructing a small tuple is ­≈6 times faster than constructing the equivalent list.

0.413 usec - 0.0602 usec = 0.3528 usec savings and the particular optimizations that makes this possible is only valid for a tuple containing constant items. I wouldn't bother with that even when microoptimizing a CPU-bound code.

>> Python's tuple is intended to be a lightweight struct.

> A list can be easily used for the same purpose. However,

> a tuple cannot be always used instead of a list. So,

> from implementation point of view, tuple is an optimized

> particular case of a list.

No it can't. A list does not carry the same semantic. A table in a relational database is precisely described as "a list of tuples", it is not a "list of lists" nor it is a "tuple of lists" nor it is a "tuple of tuples". A "tuple" has the same semantic as an "entity" or "instance" or "object", which is not the same as "collection" (list, arrays, dictionaries, etc). That a tuple is implemented as an array similar to list is just an implementation coincidence, it's just like saying that you don't need struct since you can just malloc a memory area, treat is as a char array, and use pointer arithmetic to read/write bytes at the specified offset. Do they compile to the same thing? Yes. Does tuple/struct and list/char-array have the same semantic? Hell, no!

Anna,

In a list mylist = [2,1], if you call mylist.sort() you get [1,2]. If 2,1 is a coordinate point, then sorting it to 1,2 is a REALLY BAD THING and could lead to really bad bugs.

OTOH: mytuple = 1,2 and you call mytuple.sort(), you get an error because (1,2) is not sortable. This is a GOOD THING, leading it to be usable as a hash (key) in a dict, and for identifying specific things.

A list has no business being coerced to a tuple in order to act as a key in a dict. I think that's an abuse of list. You'd be better off thinking of tuples as a record in a database. "213 1st Street" means nothing when sorted in a list ['1st', '213','Street'), but means everything when left as a tuple ('213', '1st', 'Street') as it should be. Tuples are great for data - when the position *means* something, not just an "ordering". People ask, "why don't you just have named field". A phone number doesn't really need named fields for the 800 to mean something and for it to be important that it not have its order rearranged. Take the following two tuples: (408,555,1212) and (555,408,1212). If you treat them just as lists, you could end up sorting them and they'd be "identical". But they're not identical - they're phone numbers for completely different parts of the country and the structure is meaningful. Which means, tuples would be appropriate here, and that structure is what makes them good as keys.

Stefan Sonnenberg,

Version hell.

There is no such thing with python.

Python 2.0 was a major step as 3.0 is. There is a clear path outlined

to get from 2.7 (the latest release in 2-Series) to 3, and even a tool

to help you with that (http://docs.python.org/library/2to3.html).

The quote "python 3 is for brandnew things" relates to new features of the 3-Series, not for new projects to implement in python.

Yes, support for 3 is fairly thin, but there have been troubles (and a moratorium for language changes), and some major external (read again, external) libs are not yet available.

Heading 3.2 the world will get better - and 2.7 will be supported for a while (http://docs.python.org/dev/whatsnew/2.7.html#the-future-for-python-2-x).

Incomprehensible language reference

This is where you are IMHO *absolutely* wrong.

The core language reference is in BNF, which *is* comprehensible.

The library reference *is* comprehensible, and full of examples.

That the PHP crowd mixis a syntax reference with a function reference

is not python's fault (try to get a valid BNF for PHP from their site ...).

But as always, the question is, to whom it is comprehensible.

Perhaps not to you.

BNF is a context-free language to describe grammars.

The PHP reference is definitly not context free.

Optimized data types (immutable, ranges and iterators)

IMHO the differentiation between lists, tuples and also sets

originates from math.

Yes, Python burdens a programmer to choose the right data type

for his particular case.

But what is wrong with that ?

There are always to dimensions for optimazations: time and space.

If you have only one datatype (PHP's array), you have to sacrifice

one or the other anytime soon.

Or create a super datatype, which optimizes itself during runtime.

An iterator is no datatype. Period.

When you say you like to program in C++, you should have come

accross the stdlib, which has plenty of them.

Vladimir,

May 2011, py3 is still nowhere... At the last evaluation for script lang to use in our company - we chose Ruby, simply because of the more reliable standard compared to Py, even Lua/Powershell were discussed over Python.

Martin Kunev,

PHP documentation is very poorly written. It is useful for basic topics but once you want to go deeper, it's hard to find information. For some reason the PHP people try to hide language details. Some details are missing in the PHP reference and left for the user to guess. The confusing parts and specific cases are left unexplained pretty often.

In contrast, for example the C manual pages are very detailed.

Martin Kunev,

Also, in my opinion these heystack/needle argument names are just silly. Often the role of the argument is hard to figure out from such a name.

Peter Kankowski,

"Looking at download statistics for the Python Package Index, we can see that Python 3 represents under 2% of package downloads. Worse still, almost no code is written for Python 3."

http://alexgaynor.net/2013/dec/30/about-python-3/

Willy Carfield,

I have had to maintain servers with some Python scripts for 10+ years. "There is no such thing as version hell" is a damn lie. I have had to create side-by-side installations of Python for several servers which have had Python scripts for version 2.4 and they have not worked as such after upgrade to 2.5+. Why is it that such a small change in version can break a script. Incredible.

This has happened at least a dozen times so far. I admit that being a Python professional might help the situation but I have no interest digging deep into the problems and conversions for half-a-dozen of scripts per server. I simply do not have the time and the companies I have been working with/in have had no interest in employing a Python nerd just for this single purpose. In some cases I have bought the expertise from outside - with varied happiness levels. In most cases the guys have had to rewrite small parts of the scripts due to version incompatibility - and I have seen the reports (and they look valid).

There is no other single language in my 32 years of programming that has caused so many problems and I have done worked in just about every mainstream language so far.

Mike,

I disagree with you on the syntax issue. Once upon a time, every language had such a syntax, a formal language definition that was complete and unambiguous, and could be used as the basis for writing a compiler, interpreter, syntax checker or whatever. Lately, it is common to find that the syntax is vaguely and sloppily defined.

I have all sorts of other reservations about the language, but at least it got this right, though right arrows would have been preferable to the colonitis of sticking to ASCII in a world of unicode.

Your name:


Comment:


Please ignore this field: