Gas station without pumps

2013 March 21

Why Python first?

Filed under: home school,Uncategorized — gasstationwithoutpumps @ 11:21
Tags: , , , , , , ,

On one of the mailing lists I subscribe to, I advocated for teaching Python after Scratch to kids (as I’ve done on this blog: Computer languages for kids), and one parent wanted to know why, and whether they should have used Python rather than Java in the home-school course they were teaching.  Here is my off-the-cuff reply:

Python has many advantages over Java as a first text-based language, but it is hard for me to articulate precisely which differences are the important ones.

One big difference is that Python does not require any declaration of variables. Objects are strongly typed, but names can be attached to any type of object—there is no static typing of variables. Python follows the Smalltalk tradition of “duck typing” (“If it walks like a duck and quacks like a duck, then it is a duck”). That means that operations and functions can be performed on any object that supports the necessary calls—there is no need for a complex class inheritance hierarchy.

Java has a lot of machinery that is really only useful in very large projects (where it may be essential), and this machinery interferes with the initial learning of programming concepts.

Python provides machinery that is particularly useful in small, rapid prototyping projects, which is much closer to the sorts of programming that beginners should start with. Python is in several ways much cleaner than Java (no distinction between primitive types and objects, for example), but there is a price to pay—Python can’t do much compile time optimization or error checking, because the types of objects are not known until the statements are executed. There is no enforcement of information hiding, just programmer conventions, so partitioning a large project into independent modules written by different programmers is more difficult to achieve than in statically typed languages with specified interfaces like Java.

As an example of the support for rapid prototyping, I find the “yield” statement in Python, which permits the easy creation of generator functions, a particularly useful feature for separating input parsing from processing, without having to load everything into memory at once, as is usually taught in early Java courses. Callbacks in Java are far more complicated to program.

Here is a simple example of breaking a file into space-separated words and putting the words into a hash table that counts how often they appear, then prints a list of words sorted by decreasing counts:

def readword(file_object):
    '''This generator yields one word at a time from a file-like object, using the white-space separation defined by split() to define the words.
    '''
    for line in file_object:
        words=line.strip().split()
        for word in words:
             yield word

import sys
count = dict()
for word in readword(sys.stdin):
     count[word] = count.get(word,0) +1
word_list = sorted(count.keys(), key=lambda w:count[w], reverse=True)
for word in word_list:
    print( "{:5d} {}".format(count[word], word) )

Note: there is a slightly better way using Counter instead of dict, and there are slightly more efficient ways to do the sorting—this example was chosen for minimal explanation, not because it was the most Pythonic way to write the code. Note: I typed this directly into the e-mail without testing it, but I then cut-and-pasted it into a file—it seems to work correctly, though I might prefer it if if the sort function used count and then alphabetic ordering to break ties. That can be done with one change:

word_list = sorted(count.keys(), key=lambda w:(-count[w],w))

Doing the same task in Java is certainly possible, but requires more setup, and changing the sort key is probably more effort.

Caveat: my main programming languages are Python and C++ so my knowledge of Java is a bit limited.

Bottom-line: I recommend starting kids with Scratch, then moving to Python when Scratch gets too limiting, and moving to Java only once they need to transition to an environment that requires Java (university courses that assume it, large multi-programmer projects, job, … ). It might be better for a student to learn C before picking up Java, as the need for compile-time type checking is more obvious in C, which is very close to the machine. Most of the objects-first approach to teaching programming can be better taught in Python than in either C or Java. For that matter, it might be better to include a radically different language (like Scheme) before teaching Java.

The approach I used with my son was more haphazard, and he started with various Logo and Lego languages, added Scratch and C before Scheme and then Python.  He’s been programming for about 6 years now, and has only picked up Java this year, through the Art of Problem Solving Java course, which is the only Java-after-Python course I could find for him—most Java courses would have been far too slow-paced for him.  It was still a bit low-level for him, but he found ways to challenge himself by stretching the assigned problems into more complicated ones.  His recreational programming is mostly in Python, but he does some JavaScript for web pages, and he has done a little C++ for Arduino programming (mostly the interrupt routines for the Data Logger code he wrote for me).  I think that his next steps should be more CS theory (he’s just finished an Applied Discrete Math course, and the AoPS programming course covers the basics of data structures, so he’s ready for some serious algorithm analysis), computer architecture (he’s started learning about interrupts on the Arduino, but has not had assembly language yet), and parallel programming (he’s done a little multi-threaded programming with queues for communication for the Data Logger, but has not had much parallel processing theory—Python relies pretty heavily on the global interpreter lock to avoid a lot of race conditions).

About these ads

21 Comments »

  1. Agreed, but in fewer words: We want beginners to learn how to use such basic constructs as sequential execution, unconditional branching, conditional branching, and looping as starting points. To learn these in Java one has to first learn lots of unnecessary syntax, which creates cognitive overload; the cognitive load is far smaller in Python.

    Comment by David Klappholz — 2013 March 21 @ 11:47 | Reply

  2. My son has moved from Scratch to Java without any problem. The key to teaching Java first is to keep it simple. The available textbooks are appalling – they try to teach every last concept and construct RIGHT AWAY. There is no reason on this planet for introductory students to have to learn every loop form at the beginning – while loops will do it all and teach them how to think through a loop. There is no reason to teach the infernal i++ construct when they are still struggling with the meaning of variables and assignment. There is no reason to teach switch statements when they are trying to understand conditionals. I would like to see a Java textbook that is comparable to the way Python gets taught – stripped down and simple.

    I haven’t taught Python, but after horrible experiences with PHP and struggling students, I don’t ever want to dump an untyped language on unsuspecting students again. The lack of typing in PHP led to many, many mistakes that the students could have avoided with static typing. They were forever getting confused about what kinds of information they were passing around. With static typing, the compiler would have caught their errors, but instead, they were forced to spend hours puzzling over the strange runtime errors. I think a good compiler is an introductory student’s best friend.

    Comment by Bonnie — 2013 March 22 @ 05:20 | Reply

  3. I taught with Python for two years at the high school level and have taught introductory courses in Java at the high school and college levels. I would not use Python as an introductory language again. My experience suggests that duck typing and the lack of compile-time error checking are huge minuses for the average learner. Granted, some students build strong mental models of type right away so language support is irrelevant. But I don’t think that’s true of most people and it can turn out to be a huge hurdle.

    Python is also chaotic in a lot of ways. There are often 6 different ways to do the same thing, there’s less pressure for good procedural decomposition so it’s harder to learn about scope and control flow, the version confusion between 2.x and 3.x is absolutely maddening…

    Bonnie, have you looked at Building Java Programs (http://www.buildingjavaprograms.com/)?

    Comment by Hélène Martin — 2013 March 22 @ 18:48 | Reply

    • To be clear, I’m not suggesting Python is a bad choice for that particular parent. For strong students or one-on-one situations, having a productive language can be the most important thing.

      Comment by Hélène Martin — 2013 March 22 @ 18:53 | Reply

    • I don’t find Python to be chaotic—if anything it is more regular than Java. I don’t believe that starting with strong models of types is the best way to start teaching programming—and that is a strength of Python—that you can teach iteration and naming of objects (variables) without having to worry about types for quite a while. Java forces you to deal with types very early, and I think that is the wrong way to teach programming.

      The lack of compile-time checking is a weakness of Python, but more for advanced programmers than beginners, as most of the compile-time checks that Java has and Python doesn’t have to do with the strict static typing—a concept that adds a lot of conceptual complexity for beginners, without helping them learn.

      I admit that I have not taught classes of high school students to program, and there are undoubtedly many concepts that they would struggle with that I would be surprised by, but I don’t see any real advantages for Java over Python at that level.

      Comment by gasstationwithoutpumps — 2013 March 23 @ 12:36 | Reply

      • Python and Java force you to deal with types as soon as you want to store any kind of information for later use. The major difference for a new learner is that in Python, the notion of type is completely hidden. If you tell a student “oh, you’re not allowed to call that method on this kind of thing,” it’s a much more challenging statement when you can’t explicitly tell what kind of thing you’re dealing with.

        Comment by Hélène Martin — 2013 March 23 @ 12:50 | Reply

        • One advantage of Python is that many of the methods can be called on almost any type. Array lookup and hash table lookup use the same syntax.
          Strings, lists, tuples, and other sequences can all be sliced used the same syntax. Membership in a list, set, or hash table are all tested the same way.
          As a result, you can defer both the notion of type and subtle distinctions between types until later with Python than with statically typed languages, concentrating on more fundamental concepts like the naming of things, sequential operations, iteration, and assignment operations.

          When you do get to types in Python, the concepts are simpler, because the type is associated only with the object, not with both the object and the variable that holds the object, and the type system in Python is simpler and more regular (none of the mysterious distinction between float and Float, for example).

          Probably the hardest concept in Python’s type system that would come up in a first course is the difference between mutable and immutable types.

          Comment by gasstationwithoutpumps — 2013 March 23 @ 13:27 | Reply

  4. I took a look at the table of contents for that book. No, I think it is still trying to do too much. They still think they have to do all the loop formats, for example. And why do the for loop first? It is the least general and it hides the way that a loop functions. I prefer to cover the while loop, and ONLY the while loop, in the first course. The problem with all of the textbooks is that they concentrate on programming language constructs instead of algorithms. What I would like to see, for example, in a loop chapter would be 1) the while loop syntax 2) how to trace a simple counted loop 3) lots of examples of counted loops – counting by 1’s, counting backwards, counting by 2’s, etc. 4) examples of things you can do with counted loops (totals and averages for example) 5) loops that look for a sentinel condition 6) more examples
    The only syntax in this chapter would be at the beginning, when introducing the while loop. That is in fact how I teach my CS1 course.

    My students (not my son who takes to this stuff like a duck to water) tend to struggle a lot. They don’t need a lot of syntax dumped on them in the beginning. They need lots of examples, so they can understand that there are really patterns to this kind of problem solving. Otherwise, they feel like it is some kind of magic. I really try to stress the common problem patterns that they will see over and over.

    Comment by Bonnie — 2013 March 23 @ 05:59 | Reply

    • I agree that there is a tendency to dump huge quantities of syntax in initial courses. I often refer to AP CS courses and the equivalent college courses as “Java syntax classes”, because they sacrifice so much understanding to get all the Java syntax covered.

      One of the reasons I like Python is that you can get started with much less “ritual magic” scaffolding and much less in the way of syntax than Java.

      But I will disagree on one thing—in Python, I don’t encourage the use of the “while” loop. The basic “for” loop in Python is by far the more common loop construct and easier to understand.
      Loops like “for word in word_list:” or “for i in range(3,10):” are much easier building blocks than the equivalent constructs with while loops. Going down to near-machine level with while loops would be appropriate for a C class or assembly language class, but requires keeping too much stuff in the programmer’s working memory to be good for beginning programmers.

      Comment by gasstationwithoutpumps — 2013 March 23 @ 12:45 | Reply

    • Starting with for loops is a very deliberate pedagogical choice. The notion of “repeat this thing n times” is straightforward and quite powerful. You don’t have to worry about remembering to include an update since the syntax is explicit. Fewer challenges like DeMorgan’s law, fencepost, infinite loops, etc come up. The while loop syntax may be straightforward but its usage is far from. A student who understands how to use variables to store numbers can understand all there is to know about a single for loop but there’s more to get into for while loops. Of course, the Python for loop syntax doesn’t give the opportunity for that progression, for better or worse.

      I highly encourage you to actually take a look at the book if you get the chance.

      Comment by Hélène Martin — 2013 March 23 @ 12:59 | Reply

      • Yes, but then you are stuck with only doing counted loops. I would rather do all sorts of loops – those with sentinel conditions, those with compound conditions, and so on. You can jam those kinds of conditions into for loops but it gets ugly in a hurry. Also, for loops hide too much, and my students don’t need things to be hidden. They see everything as a magic incantation The “for word in word_list” would absolutely be a magic incantation for them. I prefer having them REALLY understand what is going on, so they can form a mental model of the machine. When I teach, I trace endlessly, on the board, diagram after diagram, to encourage them to really understand the mechanics. Otherwise, it is all incantation to them.

        We spend at least two weeks simply on assignment, because otherwise they don’t GET IT. That is why I avoid things like i++, which is too much for students who struggle so with assignment. I’ve learned from years of teaching programming that even students who appear to understand the concepts easily do not really get assignment or variables, and it bites them when they need to start understanding pointers/references.

        Comment by Bonnie — 2013 March 23 @ 18:32 | Reply

  5. One of these days, when I have time, I should write my very own “Learn to program” book. Most of the books are so bad. The only one I really like is Michael Kolling’s Greenfoot book, which has the simplicity that I seek – but it isn’t really a CS1 book. I use it at the end of my CS1 course to teach the beginnings of OO design. The students really like it – they really get it, and tell me that it is the first CS book that makes sense.

    Comment by Bonnie — 2013 March 23 @ 18:34 | Reply

  6. I’ve written a Python textbook that does pretty well, and I’ve never heard of “yield” before. Digging into the docs now. What’s interesting is that Python supports spheres of programming — there are multiple sets of facilities in Python that we might use, with surprisingly little overlap between.

    Comment by Mark Guzdial — 2013 March 26 @ 11:14 | Reply

    • I have students learn Python in the context of doing bioinformatics. One of the things I try to teach is the importance of separating I/O from processing, but of extracting the essential information (often summary statistics) and discarding the rest rather than trying to store entire data sets in RAM (bioinformatics data sets are growing much faster than Moore’s law).

      The yield statement in Python makes the separation of input from processing much simpler and cleaner than in most programming languages, and so is one of the first things I have students learn. (Note: the students I’m teaching supposedly already know how to program, generally in Java—I was going to teach a first programming course this year, but the courses got reassigned so that I could create an Applied Circuits for Bioengineers course instead.) I regard the combination of Python’s for loop and generator function as more important than the while loop for most bioinformatics programs. I’ve had a couple of students who consistently used only while loops—their code was by the least readable of anyone’s in the course.

      One can certainly use Python without the notion of generators and the yield statement, and the concept is a bit tricky to teach if you insist on a bottom-up approach (since it can’t be modeled with a single stack-based control flow). But in a top-down paradigm, in which “for x in iterator:” is a basic concept, having an easy way to construct an iterator is very handy. I would think that in a media-based course it would be very useful to be able to say things like “for pixel in image.pixels():” or “for row in image.rows():” rather than having to construct the loops needed to do those iterations over and over. Separating the details of iterating over a tree or multidimensional array from what is done on each element is a valuable abstraction that Python supports in a simple way—if you bother to teach it.

      For those unfamiliar with Python iterators and yield statements, a generator function returns an iterator object. Each time time a “next” is performed on the iterator, the function runs until a “yield” statement is encountered, and value of yield is provided as the next value of the iterator, without the iterator losing track of where it is in its own control flow. If the function returns before reaching a yield statement, then the end of the iteration has been reached. The low level details of exactly how iterators are implemented do not need to be understood to use generator functions effectively.

      Comment by gasstationwithoutpumps — 2013 March 26 @ 11:41 | Reply

      • Absolutely, we do for pixel in getPixels(picture) and for sample in getSamples(sound) all the time. We just don’t use generators.

        Comment by Mark Guzdial — 2013 March 26 @ 11:49 | Reply

        • If you are doing it without generators, then I assume that you are constructing lists in functions and returning them. That approach is ok when the amount of data is small and speed is unimportant, but does not generalize well to huge data sets. Python can be very memory hungry, and memory management is usually the bottleneck in Python programs with big data, so I try to teach students from the beginning not to copy unnecessarily. The yield statement makes generators simple enough to write that I can get students used to the idea of iterating over files and data structures without copying them.

          If I weren’t teaching bioinformaticians, I would probably delay teaching “yield”, but no later than the second semester. It provides too clean a way to teach the abstraction of iteration, separate from the notion of a data structure like a list, to avoid for longer than that.

          Comment by gasstationwithoutpumps — 2013 March 26 @ 12:00 | Reply

  7. Hi,
    Any thoughts on how a kid should go about learning Python. He has completed AP CompSci.

    Thanks!

    Comment by Gunita — 2013 July 2 @ 17:07 | Reply

    • A student who has already learned some programming can probably learn a fair amount of Python from the on-line tutorials, such as http://docs.python.org/3/tutorial/. Doing some projects is the best way to learn the language. The Project Euler math puzzles are good, if the student likes math puzzles, but there are lots of other ideas for Python projects floating around the web in various course web sites (I have a bunch of bioinformatics ones in the BME 205 web pages).

      Comment by gasstationwithoutpumps — 2013 July 2 @ 18:25 | Reply

  8. Thanks a bunch- that was quick. Really appreciated your blog on topics such as how many APs is too much. Yes, he enjoys math and puzzels. There is a possibility that he’d be using Python for analyzing financial data. So cannot wait until they teach it in his AI course next fall.

    Comment by Gunita — 2013 July 2 @ 19:21 | Reply

  9. […] I also agree with the concern that making CS a “foreign language” skill will put even more pressure on high schools to adopt a common programming language.  The College Board AP test has already blessed Java, which I think is a poor choice for a first teaching language (though I know that many computer science professors like it as a first language, for many of the same reasons I dislike it).  I prefer Scratch followed by Python, as I’ve explained before on this blog. […]

    Pingback by CS is not a foreign language | Gas station without pumps — 2014 February 2 @ 07:40 | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Rubric Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 274 other followers

%d bloggers like this: