The interpreted language Python is a lot of fun. It’s great for quick and dirty lash-ups, and has list comprehensions whilst being easier to use that Haskell. There are many great reasons why you would never deploy it in a production environment, but that’s not what this article is about.
In the UK, the government decided that schoolchildren needed to learn to code; and Python was picked as the language of choice.
Superficially it looks okay; a block structured BASIC and relatively easy to learn. However, the closer I look, the worse it gets. We would be far better off with Dartmouth BASIC.
To fundamentally understand programming, you need to fundamental understand how computers work. The von Neumann architecture at the very least. Sure, you can teach CPU operation separately, but if it’s detached from your understanding of software it won’t make much sense.
I could argue that students should learn machine code (or assembler), but these days it’s only necessary to understand the principle, and a high level language like BASIC isn’t that dissimilar.
If you’re unfamiliar with BASIC, programs are made up of numbered lines, executed in order unless a GOTO is encountered. It also incorporates GOSUB/RETURN (equivalent to JSR/RTS), numeric and string variables, arrays, I/O and very little else. Just the basic building blocks (no pun intended).
Because of this it’s very quick to learn – about a dozen keywords, and familiar infix expression evaluation, and straightforward IF..THEN comparisons. There are also a few mathematical and functions, but everything else must be implemented by hand.
And these limitations are important. How is a student going to learn how to sort an array if a language has a built-in list processing library that does it all for you?
But that’s the case for using BASIC. Python appears at first glance to be a modernised BASIC, although its block structured instead of having numbered lines. That’s a disadvantage for understanding how a program is stored in sequential memory locations, but then structured languages are easier to read.
But from there on, it gets worse.
Data types are fundamental to computing. Everything is digitised and represented as an appropriate series of bits. You really need to understand this. However, for simplicity, everything in python is treated as an object, and as a result the underlying representation is completely hidden. Even the concept of a type is lost, variables are self-declaring and morph to whatever type is needed to store what’s assigned to them.
Okay, you can do some cool stuff with objects. But you won’t learn about data representation if that’s all you’ve got, and this is about teaching, right? And worse, when you move on to a language for grown-ups, you’ll be in for a culture shock.
A teaching language must have data types, preferably hard.
The next fundamental concept is data arrays; adding an index to a base to select an element. Python doesn’t have arrays. It does have some great built in container classes (aka Collections): Lists, Tuples, Sets and Dictionaries. They’re very flexible, with a rich syntax, and can be used to solve most problems. Python even implements list comprehensions. But there’s no simple array.
Having no arrays means you have to learn about the specific characteristics of all the collections, rather than simple indexing. It also means you won’t really learn simple indexing. Are we learning Python, or fundamental programming principles?
Unlike BASIC, Python is block structured. Highly structured. This isn’t a bad thing; structuring makes programs a lot easier to read even if it’s less representative of the underlying architecture. That said, I’ve found that teaching an unstructured language is the best way to get students to appreciate structuring when it’s added later.
Unfortunately, Python’s structuring syntax is horrible. It dispenses with BEGIN and END, relying on the level of indent. Python aficionados will tell you this forces programmers to indent blocks. As a teacher, I can force pupils to indent blocks many other ways. The down-side is that a space becomes significant, which ridiculous when you can’t see whether it’s there or not. If you insert a blank line for readability, you’d better make sure it actually contains the right number of spaces to keep it in the right block.
WHILE loops are support, as are FOR iteration, with BREAK and CONTINUE. But that’s about it. There’s no DO…WHILE, SWITCH or GOTO.
You can always work around these omissions:
You can also fake up a switch statement using IF…ELSEIF…ELSEIF…ELSE. Really? Apart from this being ugly and hard to read, students are going to find a full range of control statements in any other structured language they move on to.
In case you’re still simmering about citing GOTO; yes it is important. That’s what CPUs do. Occasionally you’ll need it, or at least see it. And therefore a teaching language must support it if you’re going to teach it.
And finally, we come on to the big one: Object Orientation. Students will need to learn about this, eventually. And Python supports it, so you can follow on without changing language, right? Wrong!
Initially I assumed Python supported classes similar to C++, but obviously didn’t go the whole way. Having very little need to teach advanced Python, I only recently discovered what a mistake this was. Yes, there is a Python “class”, with inheritance. Multiple inheritance, in fact. Unfortunately Python’s idea of a class is very superficial.
The first complete confusion you’ll encounter involves class attributes. As variables are auto-creating, there is no way of listing attributes at the start of the class. You can in the constructor, but it’s messy. If you do declare any variables outside a method it silently turns them into global variables in the class’s namespace. If you want a data structure, using a class without methods can be done, but is messy.
Secondly, it turns out that every member of a class is public. Always. You can’t teach the very important concepts of data hiding; how to can change the way a class works but keep the interface the same by using accessors.
And talking of interfaces, what about pure virtual functions? Nope. Well there is a way of doing it using an external module. Several, in fact. They’re messy, involving an abstract base class. And, in my opinion, they’re pointless; which is leading to the root cause why Python is a bad teaching language.
All Round Disaster
Object oriented languages really need to be compiled, or at least parsed and checked. Python is interpreted, and in such a way as it can’t possibly be compiled or sanity checked before running. Take a look at the eval() function and you’ll see why.
Everything is resolved at run-time, and if there’s a problem the program crashes out at that point. Run-time resolution is a lot of fun, but it contradictions object orientation. Things like pure virtual functions need to be checked at compile time, and generate an error if they’re not implemented in a derived class. That’s their whole point.
Underneath, Python is using objects that are designed for dynamic use and abuse. Anything goes. Self-modifying code. Anything. Order and discipline are not required.
So we’re teaching the next generation to program using a language with a wide and redundant syntax and grammar, incomplete in terms of structure, inadequate in terms of object orientation, has opaque data representation and typing; and is ultimately designed for anarchic development.
Unfortunately most Computer Science teachers are not software engineers, and Python is relatively simple for them to get started with. The problem is that they never graduate.