3
$\begingroup$

I've been recently helping someone with their beginners Python programming course at their university (though I don't think the specific language is particularly important).

At times I'm frustrated, because I seem to be unable to push them to bridge, what seems to me to be, incredibly small leaps in logic.

At one point there was a question that stated "using the solution to Q1, solve Q2, but do it for a range of numbers". They were able to do Q1 on their own, they were able to independently understand ranges in python, and how to iterate over them, and create lists with ranges. What they couldn't seem to understand, is that basically copying and pasting the code from Q1 into the for loop would do exactly what they asked.

I tried to present analogous scenarios to give hints, heck tie it to real life ("you know how to make an omelette, what do you need to do to make 10?"). They seemed to "get" these other things, but when it came to looking at code and trying to apply the same logic, they just straight up had no idea what to do.

After a long time they were not able to grasp the problem, and I didn't feel comfortable literally just telling them the answer. They eventually talked to another person who gave them a solution (not what they used) and that helped them finish their own independent solution that was 99% of the way there. After the class after the homework was due, they noted how they essentially "face palmed" after the professor explained the expected solution (basically copy paste Q1, as I described).

I think part of the issue is that they have yet to cover functions, which would make it a whole lot easier: abstract away the Q1 part of the question, and thus make it easier for them to make that leap. On the other hand I fear that I'm too far removed from the point where I had started learning to relate to their learning experiences (I remember when I didn't even understand for loops, so at least I know I had some of the same issues when I was younger).

Is there anything I can do in these types of scenarios?

$\endgroup$
  • $\begingroup$ It might sound ridiculous, but maybe your students are "afraid" of using new language constructs. Try to motivate them to play with ipython and to check the results and the data types of the variables they created. It really sounds like they're complete beginners and you should give them some time to get used to programming, the language constructs and the tools that are used! $\endgroup$ – csabinho Sep 25 at 21:33
  • $\begingroup$ Why the self-learning tag? Your question is what you as a teacher can do for your students, no? $\endgroup$ – Flater Oct 30 at 11:55
  • $\begingroup$ @Flater Good catch. $\endgroup$ – Ben I. Oct 30 at 12:21
  • $\begingroup$ Re: "they have yet to cover functions"... oh wow, you're going to really hate how much more trouble they have thinking about abstracted functions. :-/ $\endgroup$ – Daniel R. Collins Oct 31 at 18:31
2
$\begingroup$

This is hard to diagnose without much more information, but my first thought is that this student is thinking too concretely. They are thinking about values and haven't abstracted out the idea that the actual value, 3, doesn't matter, but that "the idea of a value" does.

If the student has a good understanding of math (say algebra) then a variable isn't something that varies or can take different values. It is an unknown, but it has a fixed value. The terminology in programming is the same (variable), but the idea behind it is different.

Perhaps you can explore that area to see if that is the case.

The second idea is that you are perhaps making a somewhat longer jump into iteration than the student is ready for and need to work out a few more simple examples until insight comes. And don't mean cooking eggs. Examples in code, traced out so that the flow of execution becomes more natural: the sequential nature of the execution.

Lots of other possibilities, of course. A complete diagnosis would probably require watching the student in action.

$\endgroup$
  • $\begingroup$ These were literally my exact two first thoughts! I figured there was roughly a 0% chance that you had exactly the same guesses as me, so I would make a second answer to add in whichever of the two of them you didn't mention. :) $\endgroup$ – Ben I. Sep 26 at 1:10
2
$\begingroup$

Knowing how to use a tool is different from knowing why/when to use a tool

At a basic level, there is a difference between having certain skills and learning to apply/orchestrate these skills to achieve something more complex.

Forrest Gump was a good runner, but had no knack for understanding American football and needed to be told to run when it was time for him to run. Forrest has a skill (running), but was notoriously incapable of seeing the bigger picture (how to win a football match). This is made painfully clear when Forrest does not stop running when he reaches the endzone, instead running into the stadium.

In order for students to orchestrate the separate skills they have (iteration, calculation, ...) they must first be comfortable with the skills themselves and know them like the back of their hand.

Right now, your students are Forrest Gump. You taught them to run. You have not yet taught them how to decide for themselves why/when/where they should run and why/when/where they shouldn't.

Breaking down the problem is a skill on its own

Additionally, understanding that a complex challenge can be solved using an orchestration of basic skills requires your students to learn how to break down the problem.

They seemed to "get" these other things, but when it came to looking at code and trying to apply the same logic, they just straight up had no idea what to do.

Based on your description, I infer that you're expecting this to automatically happen, but that's not the case.

After a long time they were not able to grasp the problem, and I didn't feel comfortable literally just telling them the answer.

As a teacher, if your students do not know the answer, it's counterproductive to withhold the answer from them. It's akin to the old "if you don't know what's wrong then I'm not going to tell you" joke. Clearly, the fact that they are not finding the solution means that they are currently unable to find the solution. Withholding the answer perpetuates the issue and is going to lead to dispirited students who no longer care to look for the answer when they don't know the answer yet.

Teach them to break down the problem without touching any code. Walk them through the problem description, and analyse the issue to see if you can break it down into smaller steps.

In theory, you should never tell them how to solve it. All you should do it break down the problem in smaller and smaller steps until your students realize that they already know how to solve these (sufficiently small) steps. Depending in your students' skill level, you may have to break things down repeatedly.

If they really aren't getting it, then it's time to consider if the students have have enough exposure to the rudimentary skills that you're asking them to orchestrate.

If you break down a complex problem down to e.g. number addition and students still don't respond to it ("I know how to solve that part"), then you're either dealing with disinterested students or students who aren't comfortable with the basics yet.

Functions are essential constructs toward abstraction

I think part of the issue is that they have yet to cover functions, which would make it a whole lot easier: abstract away the Q1 part of the question, and thus make it easier for them to make that leap.

Yes, this is probably the biggest factor in why they're not thinking in abstracted terms. However, it's not so much that they should already know functions.

When you introduce functions with simple examples that do not yet warrant functions, then students are left wondering what the purpose of a function is other than "to put things elsewhere". Coincidentally, my wife is taking a beginner's development course and this is exactly the stage they are at.

Rather, this is the exact moment for you to introduce functions. Let them solve Q1 on their own, and then refactor Q1 to use a function. Tell them that it's the same solution but in a different form and do not elaborate on the purpose of functions yet; only explain how it works.

Then, when you let them tackle Q2, let them do it by themselves, without any suggested for loop. Wait for them to make the mistake of copy/paste repeating themselves. More importantly, let them make that mistake.

When they've made that mistake, present a (fictional) Q3 in which you ask for them to perform this calculation for one million numbers, and then look as they all sigh and moan about the challenge.
Alternatively, you could phrase Q3 as a change to the calculation logic, which will require them to change all instances of their copy/pasted code. Bot options lead to the same result: unhappy students.

Now, you've created the perfect audience that is incentivized to learn about method abstraction and how to prevent copy/pasting in code. Refer them back to your Q1-with-a-function solution. Work out Q2 using that pre-existing function. Work out Q3 with that same function.

This will convey the importance of abstraction (functions) as opposed to brute force (copy pasting). Work smarter, not harder.

A practical example

Pythagorean theorem - calculate the hypotenuse of a right angle triangle when given the length of the other sides.

We all know the theorem, where c is the hypotenuse:

c² = a² + b²

or when we solve for c:

c = √(a² + b²)

But how do you write an application that finds the value of c?

As a developer, you immediately start breaking it down into core tasks: addition, squaring (or multiplication), square rooting.

But your students aren't going to think this way. So far, they've been introduced to problems for which there was an explicitly existing tool. Their first few challenges were all one-trick-ponies, i.e. they could be solved by knowing a particular keyword and implementing it.

Logically, they are going to expect that this challenge (just like the ones before) will have a simple one-keyword-answer, which it doesn't. Walk them through it. Tell them there is no short answer to this, they must cobble something together with what they know.

Present the challenge to your students, and ask how they are going to solve this. If no one starts breaking down the problem, ask them to do the math manually:

What is the length of the hypotenuse when the length of the other sides is 3 and 4?

When they tell you the right answer (5), ask them to show their working out. What you will get is a written-word-pseudo-code answer to the programming challenge. Something along the lines of:

I squared the 3 and the 4, I added them together, and then I calculated the square root.

As they explain this, write it down:

  • Square the numbers
  • Add them together
  • Take the square root

And now ask them if they know how to solve any of these bullet points individually.

Now, you will get students who see that the complex challenge (Pythagorean theorem) is nothing more than a combination of simpler challenges (multiplication/squaring, addition, square rooting) which they already know the answer to.

To really sell it, you could enforce that the challenge must explicitly break down the problem into these three steps:

  • Enforce that students make four separate methods:
    • calculateSquare(x)
    • add(x,y)
    • calculateSquareRoot(x)
    • calculateHypotenuse(a,b) where you've explicitly disallowed any direct calculation and are only allowing them to declare/assign variables and call the other three methods.
  • If the students still seem to struggle doing this on their own, split the students into groups of three, where each student tackles one of the three "simple" methods.
    • When they are finished creating their own methods, they can then work together at implementing the main calculateHypotenuse(a,b) method which will rely on the methods they just created.
$\endgroup$
  • 1
    $\begingroup$ There are plenty of nice insights in this answer. FWIW, when I first introduce functions to beginners, I use it as a way to introduce great, descriptive function names. The initial benefits at first sight are that we understand easily what the (no longer) large method is doing, and we have an easier time piecing back together what the code inside the function does, thanks to the great name. Using functions essentially as labels at the start gives them a clear purpose, starts students off with good naming habits, and easily leads into their further use later. $\endgroup$ – Ben I. Oct 30 at 12:27
  • $\begingroup$ Watch out for that specific example (3-4-5 right triangle), because IME the answer is often "because I memorized it [the Pythagorean triple]". Or sometimes just parroting the arithmetic sequence. $\endgroup$ – Daniel R. Collins Oct 31 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.