I find it much easier to teach language, where range(5) _is_ a list [0,1,2,3,4]
I thought so too at first but I think it was because I dislike change. When I really began to use Python 3 in earnest I came to like the idea because I've almost never taken the value of range. And teaching loops without intermediate variables is much easier.
For example I would never teach this in Python:
for i in range(10):
print mylist[i]
I would always teach this:
for i in mylist:
print(i)
Which is clearer and easier to read? Did I have to teach you the Iterator protocol in order to understand that? No. It almost never comes up until you're an advanced Python user.
In the rare case where I do need to take the value of range it becomes much more explicit:
nums = list(range(10))
If you're an old-time Python 2 user you might ask why you have to pass range to the list constructor when it returns a list itself. But if you're a new Python programmer learning Python 3 you don't have those expectations: range is something you loop over and list is happy to do that for you. You could also write it out long-hand:
nums = [i for i in range(10)]
Which could be nicer if you wanted to transform the numbers or add some conditional filters.
Over all I find Python 3 to be much more consistent in its design than Python 2 and thus easier to teach.
- object castings are not nice (for code brevity/clarity - things, which Python aims to bee good at),
- if objects are similar, it's pain to explain the difference (it's not a thought - it's a thing I had to deal with many times).
In particular, if one is advanced programmer in general, or at least has a firm grasp of Python basics, iterators are nice. But for newbies, they are harder. (And it's even harder to hand-wave that they are "somethings, which can be casted into lists".)
As a side note I dislike possibility of using tuples as iterables. It breaks "There should be one-- and preferably only one --obvious way to do it." i.e. using tuples in place where one (conceptually) should use a list.
And again, explaining difference to newbies is painful ("tuple is a handicapped list").
I don't begin teaching someone programming by explaining objects and types.
I generally start by introducing three fundamental concepts: variables, conditionals, and loops. And I keep it simple to begin with:
a = 1
print(a) # 1
a = 2
print(a) # can you guess what it will print?
Then I add conditionals:
if a == 2:
print("it is two!")
else:
print("it is not two...")
And I only really cover 'for' at first:
groceries = ["ham", "cheese", "eggs"]
for item in groceries:
print(item)
Along the way I explain some of the primitive data types: string, integer, float; and containers such as list and dictionary. And that is usually enough to get started with simple tasks. I tend to elide what functions are and just call them "commands" until later on so that I can demonstrate why looping is so cool:
import turtle
turtle.setup()
for amount in range(100):
turtle.forward(amount)
turtle.left(75)
And that usually drives home the point: grouping commands together to repeat them as many times as we wish using loops; variables hold data; and conditionals let us do different things depending on whether something is True or False.
I haven't had much trouble with this approach for years. I don't even get to explain iterables to newbies most of the time! Once in a while someone tries something like:
a = "foo"
a + 1
And they get TypeError or they pass in an object of the wrong type to a function and get ValueError. Early on this usually isn't a problem because some things just don't make sense like adding numbers and strings. However it can get confusing when learning how to look up functions and use them because we can only informally document what kinds of things a given function will take in its signature... it's an advantage and disadvantage of the duck-typing philosophy. It's a wart but one that I haven't really encountered with anyone I've taught until they're pretty far along and able to help themselves.
For example I would never teach this in Python:
I would always teach this: Which is clearer and easier to read? Did I have to teach you the Iterator protocol in order to understand that? No. It almost never comes up until you're an advanced Python user.In the rare case where I do need to take the value of range it becomes much more explicit:
If you're an old-time Python 2 user you might ask why you have to pass range to the list constructor when it returns a list itself. But if you're a new Python programmer learning Python 3 you don't have those expectations: range is something you loop over and list is happy to do that for you. You could also write it out long-hand: Which could be nicer if you wanted to transform the numbers or add some conditional filters.Over all I find Python 3 to be much more consistent in its design than Python 2 and thus easier to teach.