Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"print" in functions causes confusion #588

Open
martinosorb opened this issue Feb 3, 2022 · 7 comments
Open

"print" in functions causes confusion #588

martinosorb opened this issue Feb 3, 2022 · 7 comments
Labels
good first issue Good issue for first-time contributors type:enhancement Propose enhancement to the lesson

Comments

@martinosorb
Copy link
Contributor

martinosorb commented Feb 3, 2022

Learners that have just learned about why a function is useful will not have clearly in mind how functions are usually used in the places they are called. The first reaction I get when they see the first example of function in the lesson, which is def print_greeting(): print('Hello!') is "why don't we just write print?".

A function is best explained as a self-contained piece of code that has inputs and an output. Putting print statements in the function is kind of unusual in well-maintained functions belonging to a library, and causes a lot of confusion, because I then have to explain that there's a big difference between printing the result of an operation and returning it for printing later.

This is even more confusing when we use the Jupyter notebook, because Jupyter automatically prints the output of the last statement in a cell, so also prints a returned value. I then find myself having to explain over and over the following:

  • returned values are not necessarily printed. It's only Jupyter that prints them;
  • yes, printing inside a function is possible, but typically we also want to return values, because a printed value cannot be used by the code that calls the function (note that they haven't seen examples of how functions are usually used, only single function calls, and not eg. assignment of the output to a variable and further use);
  • if a function doesn't have a return statement, it will return None, so if we call print on its output, we get a printed 'None', which is confusing

The whole thing is very time consuming and confusing.

Therefore I propose the following: the functions episode should be rewritten to avoid functions that contain calls to print, at least at the beginning. A more appropriate example is something like def square(x): return x*x. In this way the idea of what a function is useful for is more clear.

Only at the end, we show that it's possible to build functions that don't return anything, and/or functions that contain calls to print (but to be honest I wouldn't even do that at all).

@alee alee added good first issue Good issue for first-time contributors type:enhancement Propose enhancement to the lesson labels Feb 3, 2022
@fercer
Copy link

fercer commented Apr 9, 2022

I think that the first example is introducing what a function is without having to explain the concept of arguments.
Also, this shows that a function does not require any argument at all when defined.

As you mentioned, the example of having a function with a single print can be confusing.
Maybe having a more lines in that function can express the idea in a better way,
Something like

def print_greetin():
    print('Hello!')
    print('The weather is nice today.')
    print('Right?')

@sstevens2
Copy link
Contributor

FYI, I'm going to make a PR adding @fercer's recommendation next week as apart of a demo on how to edit lessons in GitHub for CarpentryCon next week.

sstevens2 added a commit to sstevens2/python-novice-gapminder-675 that referenced this issue Aug 10, 2022
@rashid-bioinfo
Copy link

If you want to avoid print statement in a function definition, then save the value in a variable and return that variable, on calling that variable will print whatever stored in that variable. For example:

def somefunc():
... x = 'That was a waste of my time'
... return x
...
somefunc()
'That was a waste of my time'

@brownsarahm
Copy link

I understand the goal to introduce a function without arguments. I am curious, however, about the risk of creating an initial mental model that learners will struggle to update and that promotes bad habits (side effects instead of returns) of the type that make code harder to debug and use later. There are some "bad habits" that only impact performance nominally in a modern computer, but this one is the type that I see my computer science students in my regular job outside of the Carpentries struggle with the effects of. For example tests not passing when their "function does the right thing" because they use print instead of return.

What learners see first is going to get extra weight and be considered the default, whether that was the goal when it was written that way or not.

I propose something like

def make_greeting(name):
    return "Hello " + name

At this point in the lesson, the learners have already seen lots of arguments when using builtin functions and libraries, so this is more showing them behind the scenes of what they already know than introducing too many things at once. They have also already seen docstrings in help, so they know that function calls can look approximately like this.

I think at this point in the lesson a mental model that will serve them is more important than the minimal code that will run.

Starting with what is best practice, even if a bit more complex, still fits within Carpentries pedagogy.

@martinosorb
Copy link
Contributor Author

I agree, Sarah, and that's the idea behind my initial post. For me the basic mental model of a function should be a machine that turns inputs into outputs -- many people will also already have the mathematical definition in mind, of y = f(x). I like what you propose.

@brownsarahm
Copy link

I avoided a math one for the case of math being distracting and anxiety inducing, but yes I was attempting to agree with you while changing the themes in the lesson as little as possible

@gyengen
Copy link

gyengen commented Mar 22, 2023

Students don't tend to understand what is the point using a function. Using examples like a function without proper input or output (even worse using print functions inside) will usually just make things worse. I think the biggest issue is that we are using too simple source codes as examples where functions are indeed unnecessary.

Therefore these simple examples fail to demonstrate really useful features of functions like:

  • making your code nice and tidy,
  • recall the functions with different inputs (no copy and paste as function works as a template).

@martinosorb I would avoid using math examples when teaching functions. It could just make some people anxious who thinks they will not understand it because of some lack of knowledge in maths.

zkamvar pushed a commit that referenced this issue May 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good issue for first-time contributors type:enhancement Propose enhancement to the lesson
Projects
None yet
Development

No branches or pull requests

7 participants