Setting out to learn Python. Anyone wanna join?

You should give them that feedback Malor. Obviously you should use a less emotional tone and just detail the facts plus reason that it is causing you to wonder if you missed a step. (whether you think that is the case or not it will draw upon the instructor's inherent desire to help, answer questions or respond to interest)

You may even ask them if statistics is required background for the class.

I would assume that it would be in the program's best interest to make sure that all the courses are on par in quality.

I had signed up for the R courses to take with my wife (she's in stats). Her work schedule didn't permit doing them right now and I didn't get started either. The forums were filled with reviews like Malor's though.

You should give them that feedback Malor.

Well, I already dropped out, so I don't think I can do that anymore.

the instructor's inherent desire to help

He seems like a nice guy, and I think he really wants to share what he knows, but he's literally, in the second week, talking about defining functions inside functions and the implications that has for variable scoping.

I could certainly see getting into nested functions later on, because they can obviously be very useful, but spending all that time on nesting functions, when the students haven't successfully written a function yet, seems completely disconnected from reality. Advanced usage is great, but teach me the basics first, and give me a chance to practice.

I think a better approach would have been to say, "you can define nested functions, but don't do that yet, because thar be dragons. We'll talk more about that a few courses from now." That would have freed up tons of lecture time for, say, handling concrete examples of file I/O.

I'm sure I could have figured out this week's assignment, but it felt like I'd be learning R on my own, roughly from scratch, to do so, and if I'm going to do that anyway, why take a class?

I've been noodling my way through Project Euler, and had a lot of fun with Problem 61:

Find the sum of the only ordered set of six cyclic 4-digit numbers for which each polygonal type: triangle, square, pentagonal, hexagonal, heptagonal, and octagonal, is represented by a different number in the set.

(they define what those are, but I won't quote that part.)

The reason this was fun is because I was generating such horrible code at first. I knew it needed recursion for a reasonably elegant solution, but my first several attempts were pretty much disasters. I got lost in complexity, because I didn't see the simpler answer at first, and was generating completely nonsense results. I finally sat down again today and rewrote the whole thing from scratch, and after a little debugging, nailed it.

There is, actually, a fairly elegant way to find this answer, and I ended up with Python code that takes about 0.55 seconds to run. I'm sure it would be faster in a quicker language; I bet C# could do it in under a tenth.

Compare that with my first attempts, which looked to take hours, on a 3GHz Haswell box, to generate the wrong answers.

(My very first attempt was exhausting the RAM of the 8 gig machine I was running it on!)

I gots to get me on some Project Euler. I have a problem making time, and keeping to what I've made the time for, but it touches on a few interests.

2nd Coursera class is live now. I've only just started the videos but this is looking to be a lot more interesting and challenging. Which might be a bit of a problem. Before I'd squeeze the videos in during the week and just knock out the quiz and mini-project on Saturday morning. It's sounding like these are going to require more effort now and I've got a couple of vacations going on during the class too. Programming while camping!

For whoever said they had trouble remembering Coursera deadlines: http://help.coursera.org/customer/po...

I've only just started the videos but this is looking to be a lot more interesting and challenging.

Yeah, there was a lot to learn this week, much of it being the new infrastructure. I just now finished my 2048 implementation. Both Solitaire Mancala and 2048 were about as tough on their own as the projects in prior weeks were, for different reasons: learning the new tools in Mancala, and getting the much more complex algorithms right in 2048.

It was kind of tricky, but I learned something: I'd been incorrectly using the "next" command to skip single iterations in loops, and what I actually wanted was "continue". I guess my code has been structured well enough that it didn't bite me until now. Pylint helped me find that problem, which I'm grateful for.

However, I ended up having to make a junk variable because pylint is also stupid: I was using an index variable to loop a certain number of times, and it dinged me for not using the index in the loop. I ended up assigning it to self.crap_variable, just to shut it up and get all the points.

Definitely seeing the value in the test infrastructure... adjusting an algorithm while chasing down subtle bugs is much easier when you can instantly bang on your changes twenty different ways.

edit to add: In my move function, I ended up with *almost* a single code path for all four directions, but I felt I had to implement a test on direction to tell me how far to go. (If up or down, make distance equal to height; left or right, distance is width, since the grid might not have the same height and width.)

If it were purely my code, I'd probably have added a third distance variable to the tuples with the base addresses for the rows and columns, but I wasn't sure whether that would break the tester. I'm unclear on exactly what they're testing, so I played it safe, and used a couple of ifs, rather than doing that much restructuring of their suggestions.

Another thought I just had: it's kind of a shame that the evaluation is automated now, because the code is getting complex enough that I feel I'd benefit both from seeing other implementations, and having other people look at mine. That wasn't such a big deal in the first course, but it would be handy here, and we're not doing it anymore.

How many of us are in this second phase? Maybe we could do a peer review here, with the benefit of actual conversation rather than just vague commentary. I know there were times in the peer review of the previous course that I would have liked to talk to either the person reviewing me or the coder I was reviewing.

Malor wrote:

However, I ended up having to make a junk variable because pylint is also stupid: I was using an index variable to loop a certain number of times, and it dinged me for not using the index in the loop. I ended up assigning it to self.crap_variable, just to shut it up and get all the points.

enumerate?
I am confuse.

I wish I had saw this thread earlier, I would have done these classes with you guys. Since I have to wait until later in the year to start the first class on coursera I'm thinking about trying some of the computer science classes on saylor.org.

boogle wrote:
Malor wrote:

However, I ended up having to make a junk variable because pylint is also stupid: I was using an index variable to loop a certain number of times, and it dinged me for not using the index in the loop. I ended up assigning it to self.crap_variable, just to shut it up and get all the points.

enumerate?
I am confuse.

Well, this is the code in question:

new_grid = [] for index in range(self._height): self.crapvariable = index new_grid.append([0]*self._width) self._grid = new_grid

Without the assignment to crapvariable, pylint was mad at me.

In looking at it now, I could probably also have done it this way:

new_list = [0] * self._width self._grid = [new_list] * self._height

but I haven't tested that.

Pylint also doesn't like this usage:

new_list = [0 for item in range(self._width)]

which is, admittedly, a slightly strange way to do that, but isn't actually wrong.

I got kind of gunshy with multiplying lists because I was having big issues with it in Python3.... it was really acting up in one of my Project Euler programs. Those two forms of iteration were how i worked around the problem, and I tend to be a creature of habit.

Maybe we could do a peer review here, with the benefit of actual conversation rather than just vague commentary.

Well, we'd probably have to pass links around in PM, because I don't think we're supposed to post full implementations in public. But I'd definitely be game.

Oh. I use a leading underscore (or just an underscore) to mark a variable as dummy.

so something like

new_grid = [] for _ in range(self._height): new_grid.append([0]*self._width) self._grid = new_grid

But really that is copying references in [0]*self._width when you want new things so instead

for _i in range(self._height): row = [] for _j in range(self._width): row.append(0) new_grid.append(row) self._grid = new_grid

This can be simplified using list comps (I'm doing both at once, I can rewrite it in the AM if someone wants it) to

self._grid = [[0 for j in range(self._width)] for i in range(self._height)]

Also disregard pylint for dumb stuff like that. Readability is always the number one rule and many times an i here or a j there is more readable than _.

Well, the thing is, I can't disregard Pylint for this class, because I lose points if it bitches. We're also not allowed to use variables of less than three letters, so the nice clear i,j,k syntax for integer loops is out. So I'm stuck with index/index2/index3, which annoys me.

Malor wrote:

Well, the thing is, I can't disregard Pylint for this class, because I lose points if it bitches. We're also not allowed to use variables of less than three letters, so the nice clear i,j,k syntax for integer loops is out. So I'm stuck with index/index2/index3, which annoys me.

Do you have a copy of the pylintrc they use?
I think the leading underscore avoids the pylint variable naming and use checker.

Do you have a copy of the pylintrc they use?

I don't think they give that to us. I certainly haven't seen it mentioned.

I'll try sneaking some _i variables through next week, just to see if it works. I'm already done with this week, and I don't really feel like messing with it now.

Another thought just occurred a minute ago, on the difference between this class and the R class I dropped... this week was definitely challenging, but I felt I was given all the tools I needed in order to succeed, even to the point of being given clear implementation instructions. The only thing I was wrestling here was the recalcitrance of my own brain, and its refusal to come up with good algorithms.

An analogy that comes to mind is that this course assumes I know a fair bit about hammers and nails and saws, and gives me a nice test to be sure I know enough. Then it gives me a pile of lumber, and the frame for a house, and tells me to finish it.

The R class, in comparison, told me how to find hammers and nails, gave me a bunch of weird abstract theory on the load-bearing properties of lumber when wet and dry, and then told me to build a house from scratch.

I joined this even though I didn't do the original course last time around. I've been playing around with simple programs in Python 2 and 3 on and off for a year or so, mostly using a hodgepodge of online guides to help me learn and have built some simple stuff, mostly to help me with paperwork at work. I did the intro quiz and got 85% (and I think they gypped me on one) so hopefully I can keep up for this one. How much did they go into classes last time? I have a basic knowledge of how to write one but still don't think I fully grok why they're even needed.

I probably won't be able to tackle the projects seriously until the weekend but it'll be nice to hear others' input.

Well, they didn't really get into classes until the last couple of weeks, but the last project in particular made very heavy use of them.

They're not actually that difficult, but studying up on them is almost certainly going to be needed, because you're forbidden from using globals. Unless you store values in simplegui text fields or something, you'll need classes if you want any overall state in your programs.

Remember ya'll, classes are just fancy dicts.
Cause it's python and everything is a dictionary.

Starting from zero knowledge/experience, I feel like I am making good progress.

I started with Codecademy, until about 60+% completion, at which point I didn't feel like it was explaining enough for me to understand and I needed more depth to the instruction.

I jumped over to Learn Python the Hard Way, which was exactly what I was looking for -- until it got into classes and objects and kind of sent me off on my own to make a program. I felt like I needed more instruction.

I then went through the Google Python course, which filled in some more stuff. I finished the last assignment this morning. The exercises where challenging, but satisfying. Sure, I got stuck and needed to peek at (part of) the solution to fix that niggling error I couldn't quite figure out -- but it came together for me and I feel comfortable with what was taught. I think one of the more important things I learned from the Google course was building incrementally and checking what your functions and variables are doing by printing results during the intermediate steps.

Now, I'm back to finish up Codecademy, and flying along. It feels great.

DonD wrote:

Starting from zero knowledge/experience, I feel like I am making good progress.

I started with Codecademy, until about 60+% completion, at which point I didn't feel like it was explaining enough for me to understand and I needed more depth to the instruction.

I jumped over to Learn Python the Hard Way, which was exactly what I was looking for -- until it got into classes and objects and kind of sent me off on my own to make a program. I felt like I needed more instruction.

I then went through the Google Python course, which filled in some more stuff. I finished the last assignment this morning. The exercises where challenging, but satisfying. Sure, I got stuck and needed to peek at (part of) the solution to fix that niggling error I couldn't quite figure out -- but it came together for me and I feel comfortable with what was taught. I think one of the more important things I learned from the Google course was building incrementally and checking what your functions and variables are doing by printing results during the intermediate steps.

Now, I'm back to finish up Codecademy, and flying along. It feels great.

Here's the thing about classes. You can get away with using them extremely sparingly.

boogle wrote:

Remember ya'll, classes are just fancy dicts.

This is actually surprisingly helpful and makes sense based on what I've learned about them so far. I'll run with this paradigm for awhile and see how far it gets me.

boogle wrote:

Here's the thing about classes. You can get away with using them extremely sparingly.

Well, in most real programming, you can get away without using them at all; a huge number of very powerful programs are written in languages that aren't object-oriented. I'm pretty sure OO was grafted onto Python later; I don't believe it has the concept in its roots, although the graft is smooth, and it looks more or less native.

I don't really think well in objects, as I first learned to program when BASIC was king, and 'structured programming' was a new idea... that is, you wrote programs to have functions with nice clear entrance and exit points, and a nice clear structure.... this was when "GOTO considered harmful!" was big news. Long, long time ago.

But, despite it not being a native thought process, I gotta say, sometimes it's a nice abstraction. You can do basically anything from an OO language yourself, and sometimes faster, but the built-in syntax is clean, and the data model is convenient for isolation.

For instance, in the Mancala homework, one of the methods of the class was supposed to be plan(), which was to return a list of best moves. A nice easy way to do that was to actually create another object of the Mancala class inside the plan() method, and then copy the current state there, which let it manipulate the other object, seeing what the results of moves were, and then finally return a list of moves, never having changed its own permanent state at all.

You could certainly do that with an imperative language (just copy the data structures, and pass those as arguments to functions), but the code to do that could be a little snarly, and it would be prone to bugs, particularly if you updated your internal data format later on. Doing it with the OO syntax, on the other hand, was fast, simple, and elegant, and should continue to work well no matter what internal changes the class might go through.

Malor wrote:
boogle wrote:

Here's the thing about classes. You can get away with using them extremely sparingly.

Well, in most real programming, you can get away without using them at all; a huge number of very powerful programs are written in languages that aren't object-oriented. I'm pretty sure OO was grafted onto Python later; I don't believe it has the concept in its roots, although the graft is smooth, and it looks more or less native.

That's correct. The graft looks smooth...until you drill down into to it a bit.
The OO is pretty grafted onto python which has some weirdness to it.
For instance, note that every method takes self as a first parameter. This is because methods are really functions shoved in the __dict__ of classes.
Then, let's say you have A an instance of the apple class and O an instance of an orange class. They both have .cut() methods, which operate differently.
What do you think A.cut(self=O) does?

Spoiler:

A's cut method will run, with self referring to O, meaning any state change happens on O

edit: I misread your post, boogle. After rereading and realizing that you weren't saying what I thought, I changed this post almost completely.

A's cut method will run,

I think that's kind of how it works in all languages.... within a given class, all objects share the same code block or blocks. It lives in the same chunk or chunks of memory. The way the code knows that it's currently A or O is because it's given a pointer to a unique chunk of RAM for each. Python passes that pointer as 'self', where other languages may hide it and/or make it implicit, but they still do it.

A's method, in other words, is exactly the same as O's method, if they're the same class. The fundamental difference between the two, as far as their class methods are concerned, is that pointer. I'm pretty sure you can mess with it in various ways in other languages, too, so even if two classes are different, getting A's code to run on O's memory is probably possible in most or all of them, but it's almost always going to be a bad idea. Python makes it easy, but it's still bad.

I didn't really grok how OO worked until a few years ago, when I saw a disassembly and analysis of malware of some kind. The actual compiled output of a couple of small methods finally turned the light on in my head.... I finally understood that classes are code, and that objects are a memory block that's used by that code.

Python making self visible is a little odd, but it's still fundamentally doing what other languages are doing. You can just see the bolted-on bit there.

edit: I had a bunch more stuff here, based on a misreading of what you said, so I'm just deleting it.

DonD wrote:

Starting from zero knowledge/experience, I feel like I am making good progress.

I started with Codecademy, until about 60+% completion, at which point I didn't feel like it was explaining enough for me to understand and I needed more depth to the instruction.

I jumped over to Learn Python the Hard Way, which was exactly what I was looking for -- until it got into classes and objects and kind of sent me off on my own to make a program. I felt like I needed more instruction.

[Insert Coursera]

Now, I'm back to finish up Codecademy, and flying along. It feels great.

My exact same path... with a little modification

I'm doing the bitwise operator part on Codecademy. I'm starting to get it, but why am I supposed to know all this? Seems a bit unrelated to everything else, and they hardly explain anything about it.

Malor wrote:

edit: I misread your post, boogle. After rereading and realizing that you weren't saying what I thought, I changed this post almost completely.

A's cut method will run,

I think that's kind of how it works in all languages.... within a given class, all objects share the same code block or blocks. It lives in the same chunk or chunks of memory. The way the code knows that it's currently A or O is because it's given a pointer to a unique chunk of RAM for each. Python passes that pointer as 'self', where other languages may hide it and/or make it implicit, but they still do it.

A's method, in other words, is exactly the same as O's method, if they're the same class.

The explicit self passing is nice.
(Note I'm specifically talking about when A and O are instances of different classes.