Let me preface by adding "to Computer Science/Engineering majors". I think Python is a fine language and that it is very useful in a lot of situations, but I also think using Python as a foundational language is setting students up for a lot of unnecessary headache later on.

Syntax and semantics

My main gripe with Python is the syntax and semantics. Python looks something like this:

def some_func(var_one, var_two):
	for i in range(10):
    	num = i
    # we can still see num here
some_func("thing1", "thing2")

Right off the bat you should notice a few things, the lack of types, functional scope, and the lack of curly braces. The typing issue I can get over, Python is meant to be dynamically typed, and it is not as weird about it as JavaScript is and it recently added support for defining variable types in function parameters so it's OK in my book.

However Python does suffer from the same scoping issue as JavaScript, and scoping is done on a functional, rather than block, level. This can be confusing, especially since Python takes the insanity a step further and gets rid of the var ,let ,const keywords entirely, meaning there is not even a concept of a constant variable in Python.

Lastly, the most obvious difference from most languages you have likely seen is that there are no curly braces. This is because Python decided it would be a fun idea to govern blocks using whitespace, instead of wrapping everything in braces. In theory this might seem OK since you should already be properly indenting blocks of code, however in practice I find that it is much less legible and more kludgy to work with.

Naming Quirks

Python also decided to go above and beyond and do things differently from most other languages. Part of this is the break from C-Style syntax, and they also name things differently. For instance, what is called an "Array" in pretty much every mainstream language, is instead called a "List" in Python. Key-Value stores that are usually called a "Map" or a "HashMap" are instead referred to as a "Dictionary".


Then there are Strings, Strings in Python are horribly over-complicated. In most languages you have a char which is a single character, you can have a char[] or just an array of characters, and then a String that is usually some fancy wrapper around a regular char[]. When creating a string in most mainstream languages you can usually just do something along the lines of var s = "string" or for a char you usually use single quotes var c = 'c'. Python decided this was too simple and not specific enough. You can create a string the "normal" way, s = "string" or you can use single quotes s = 'string' or if you want a unicode string you would do uni = u'unicode' or you can craft a binary string bin = b'some binary'. You can also tell it directly what encoding you want to use, utf = "some string".encode("utf-8"). And you can also cast to string using string = str("something") because why not add another way to do things? Now I'm not saying its bad to specify what encoding you're using, but maybe if you could make it a bit more clear or use a syntax that is more common.

Version split

Another issue with Python is that it is essentially two different languages, there's Python 2.7 and Python 3+. Code written using Python <= 2.7 will sometimes work on Python 3+, and code written using Python 3+ will sometimes work with Python <= 2.7. This is because there were quite a few breaking changes introduced, that make many features that worked in 2.7, no longer work, or work differently in 3+. This as simple as the print function now work differently, for instance:

print 'Hello World'

will work using Python <= 2.7, however with Python 3+ this will raise a SyntaxError as you have to do

print('Hello World')

Another popular feature in Python 2 was xrange which basically created an iterable object that is useful, and a bit quicker than range, in for loops. However, it was simply removed in Python 3. So, if I wanted to write the same code as above to be compatible for python 2.7, I would do something like this:

def some_func(var_one, var_two):
	for i in xrange(10):
    	num = i
    	print i
    # we can still see num here
    print num
some_func("thing1", "thing2")

It is very common for languages to introduce new, backwards incompatible features. Especially with major revisions. However it is fairly uncommon to break so many widely used parts of the language that most code written before 3 simply cannot be run on the newer interpreter. The fact is that so much was broken that the community essentially split, and many people are staying on Python 2.7 as their libraries wont work on 3+ or they don't want to maintain 2 version of their codebase for backwards compatibility. This means that even though you are coding in 'Python', depending on which version you pick you are isolating yourself to a subset of the possible libraries or dependencies you can use.

All of these issues, and more, contribute to some serious headaches for new programmers. If you start by learning Python as a foundational language, when you inevitably switch to another language like C++ or Java, you have to learn an entire new vocabulary and grammar on top of the more difficult concepts as well. And Python's many quirks and irregularities don't make it the simplest language to learn from the get-go either.