On Saturday, August 9, 2014 9:04:22 PM UTC+5:30, Roy Smith wrote: > Rustom Mody wrote:
> > [To the OP] > > Yeah I am in the minority at least out here in considering > > comprehensions simpler than loops. Take your pick > When comprehensions first came out, I stubbornly refused to get my head > around them. Now, I'm totally addicted. To the extent that I consider > dict comprehensions to the THE killer feature of 2.7 :-) Yeah I remember seeing a stunning example from Peter Otten a few months(?) ago... first I heard of them. If someone can track that example down... I'll be mighty pleased. > But, putting on my instructor's hat, I think it's important to answer > questions at a level that can be understood by the student. Painting > with a broad brush, there's three or four kinds of people asking > questions on this list: > 1) People who are totally new to programming, and are learning Python as > their first language. These are the people who are still struggling to > understand fundamental concepts. They haven't figured out yet that the > first step to solving a problem is to decide what algorithms you're > going to use, and only then can you start translating that into code. > They need to be led in small steps towards basic knowledge. > 2) People who are (at least somewhat) experienced programmers, and are > learning Python as a second language. Their experiential background is > limited to one way of doing things (i.e. the Java way, or the PHP way, > or whatever language way they learned first). They mostly should be > shown how translate the things they already know into familiar feeling > constructs. You already know how to write a loop, this is how we do it > in Python. You already know how build a data structure that maps keys > to values, this is how we do it in Python. Only after they've become > comfortable with that, should they start exploring the really cool > features of Python. > 3) People who already know many languages, and are learning Python as > their n-th. These folks have seen multiple ways of doing things, and > can understand concepts at a higher level. Oh, Python dicts are more > like C++ STL maps than PHP arrays. Oh, variables have function scope > and don't have to be explicitly declared. Oh, RAII is spelled "with" in > this language. Oh, functions are first-class objects, but code blocks > are not. > 4) People who are already proficient Python programmers and are looking > to explore deeper topics. > I think suggesting comprehensions in an answer should be reserved for > people at levels 3 and 4. Maybe level 2-1/2. Certainly not level 1. All this... (and in particular) > They haven't figured out yet that the > first step to solving a problem is to decide what algorithms you're > going to use, and only then can you start translating that into code. > They need to be led in small steps towards basic knowledge. makes perfect sense... under one assumption: viz. The 'first steps' to becoming a programmer are necessarily imperative steps. So much so that programming is usually *defined* as imperative programming. This usually goes thus: - CS is defined as the science of algorithms (or algorithmics) - Programming (in the layman sense: python, java, C etc) is just about converting these 'abstract algorithms' into executable code - And an algorithm? An algorithm is an effective method expressed as a finite list[1] of well-defined instructions[2] for calculating a function. quoting http://en.wikipedia.org/wiki/Algorithm In my view this is starting from the wrong end. I do not need to know which kind of adder the hardware is implementing to use +, which sorting algorithm to use sort, etc. IOW the 'calculating a function' is primary and the 'effective steps' is secondary and traditional programming pedagogy gets this order wrong. What do I need to know to use sort? Nothing? Not so. I should be able to distinguish a sorted list from an unsorted one. This is primary. Getting from one to the other -- the how -- is secondary. [This also BTW implies that in the python world the 'sorted' function is more fundamental than the sort (mutating) method. And their names are pedagogically the wrong way round. Of course this is for historical reasons. But for now let us wear instructor not historian hats shall we?] As a more demonstrative example of the above (abstract) talk, in the 90s I used to teach a first course in programming using a predecessor of haskell (gofer -- gofer stands for GOod For Equational Reasoning). By the end of the course students could - handle data structures like generic n-ary trees, graphs etc - write toy interpreters, compilers, semantic functions - combinatorial enumerators corresponding to various types of combinatorial functions like ⁿCr ⁿPr Catalan numbers All WITHOUT a single assignment statement [very easy to accomplish since the language has no assignment statement :-) ] and more important (and germane to this thread) NO PRINT statement. I believe this is more important than the NO ASSIGNMENT. Assignments can become a religious issue one way or other. However if beginning students start off writing print statements too easily, it becomes very hard to progress from toy egs to more reusable, modular stuff. So yes I may have been a bit remiss in missing pedagogic steps in showing: >>> def index_all(lst, val): return (i for i,v in enumerate(lst) if v == val) Perhaps a right in between step would be a point in the spectrum between mine and Steven's > def index_all(source, target): > results = [] > for i, obj in enumerate(source): > if obj == target: > results.append(i) > return results viz. def index_all(source, target): for i, obj in enumerate(source): if obj == target: yield i And now someone is going to say: "yield (generators/iterators etc) are advanced whereas lists (append etc) are easier" and the argument loop starts over! So before that comes let me preempt by saying that when I write the python def index_all(lst, val): return (i for i,v in enumerate(lst) if v == val) I am using python as 'assembly language' (so to speak) and using a pidgin Haskell-ish math language to think with in which it would look something like {i | (i,v) ∈ zip.lst.[0...], v = val } IOW as long as we think (and teach) that a comprehension:* squares = [x**2 for x in range(10)] is equivalent to squares = [] for x in range(10): squares.append(x**2) the comprehensions will seem advanced but ultimately an engineering trick. Instead if we treated the python: [x**2 for x in range(10)] as an executable version for the standard set-theory expression: {x² | x ∈ [0..10) } then it would - not seem difficult/advanced etc - it would be seen/felt to be more fundamental and not just an engineering trick * I have to say that this example comes from the official tutorial itself... Unfortunate... -- https://mail.python.org/mailman/listinfo/python-list