Another year, another set of bright-eyed enthusiastic students.
Now we're coming to the end of the first semester, here is 3 more common mistakes I've come across whilst teaching beginners.
Copying and Pasting Code
This is a bugbear more than anything; however, it does have some potentially serious side effects. It is slightly different to the classic copying and pasting from a source without understanding what the code is doing
Without fail this crops up every year, a completely random error in perfectly fine looking code.
Take a look at this:
x = 100
print(x)
If I copy and paste that snippet in to Visual Code and try to run it I get:
x = 100
^
SyntaxError: invalid syntax
Uhhh, what? I'm pretty sure that is how you assign a value to a variable...
So why does it fail...? Because I've added a hidden character to it.
The problem here is I've had new developers sit and stare at their screen in frustration for longer than they care to admit because they can't figure out why this seemingly simple piece of code doesn't run.
Just be careful when copying code from PDFs, online, or wherever because quite often you'll run in to random errors but more importantly you may even end up copying something malicious.
Of course you could end up with someone doing it on purpose like a certain lecturer I had at University to force us to write the code out...
Variable Scope
What does this snippet print?
x = 5
def foo():
x = 20
print(x)
foo()
print(x)
Those that said 20
then 5
give yourself a pat on the back.
We had just introduced the concept of functions to the students, and how to use them to eliminate repeated parts of their code, and all of a sudden it was acting weird.
What the above snippet demonstrates is local function v.s. global scope. x
here is defined inside the function as a local variable to that function that shadows the global variable named x
.
Python uses the LEGB (Local, Enclosed, Global, Built-in) rule when resolving variable scope. This is the snippet I use to show students how scope bubbles up:
from math import pi
#pi = 10
def foo():
#pi = 20
print("local: ", pi)
def bar():
#pi = 30
print("enclosed: ", pi)
bar()
foo()
print("global: ", pi)
Which gives
local: 3.141592653589793
enclosed: 3.141592653589793
global: 3.141592653589793
Or with the pi
variable declarations uncommented:
local: 20
enclosed: 30
global: 10
So what is the output when I try this next snippet?
x = 5
def foo():
x = x + 2
print(x)
foo()
2? No… 7? Nope… UnboundLocalError
? Yep.
But why? The other example quite happily gave us 10
when just printing!
There are some good and in-depth explanations as to why this is the case and do a much better job of explaining the why than I could here.
Nonetheless, the solution to this is adding the global
definition so that Python knows where to find the value of x
before assignment:
x = 5
def foo():
global x
x = x + 2
print(x)
foo()
Redefining Built-in Functions
This really is a follow on from the previous point about scope and how it can crop up in other places.
... snip...
input = ("Continue? (Y/N): ")
... snip...
A fair number of students had this in their code where they had accidentally redefined the input function in the program, then tried to use it later on.
As the pi
example demonstrated what has happened is input
now has the value of that string rather than being the built-in input
function.
Top comments (4)
the "good" link is giving 404
It opens dev.to/thatonejakeb/"https://nbvie..."
instead of
nbviewer.jupyter.org/github/rasbt/...
same situation with the "in-depth" link
Thanks for pointing that out, both fixed :)
The first example (printing 5 and 20) is the wrong way around, because you're printing the global variable after the local one.
Typo, fixed, cheers boss (: