Question from a newbie

Hey All,

I am having trouble learning this at code academy. Apologies for a stupid question:

Here is the code:

shopping_list = [“banana”, “orange”, “apple”]
stock = {“banana”: 6,“apple”: 0,“orange”: 32,“pear”: 15}
prices = {“banana”: 4,“apple”: 2,“orange”: 1.5,“pear”: 3}
def compute_bill(food):
total = 0
for i in food:
if stock[i] > 0:
total += prices[i]
stock[i] -= 1
return total
print (compute_bill)

The lesson says my code is correct and I verified it with the help section. However, I do not understand it.

I have not defined “food” anywhere. How does the program or the loop know I am referring to the shopping list the other two dictionaries?

I entered it into Thonny and it tells me this is wrong code, but code academy tells me this is correct.

I am confused.

You have defined a function that takes a single argument:

def compute_bill(food):

So you need to call it that way in your code (with parentheses and an argument). But in your code, you just print the object itself.

print (compute_bill)

To call the function, you’d probably want something similar instead to

print (compute_bill(shopping_list))

Here is the code:

shopping_list = [“banana”, “orange”, “apple”]
stock = {“banana”: 6,“apple”: 0,“orange”: 32,“pear”: 15}
prices = {“banana”: 4,“apple”: 2,“orange”: 1.5,“pear”: 3}
def compute_bill(food):
total = 0
for i in food:
if stock[i] > 0:
total += prices[i]
stock[i] -= 1
return total

I think the “return” above is indented too far. It should be aligned
under the “for”. Otherwise it is part of the if-statement, and will only
run in the “true” circumstance. Worse, if the true situation occurs the
return will happen immediately, rather than finishing the loop and
completing the total.

       print (compute_bill)

This also seems overly indented, and also odd. Printing compute_bill
only prints the reference to the function; it does not call it.

The lesson says my code is correct and I verified it with the help section.

Maybe you could explain what that means (“correct” and “verified”).

However, I do not understand it.
I have not defined “food” anywhere. How does the program or the loop
know I am referring to the shopping list the other two dictionaries?

You’ve defined the function like this:

def compute_bill(food):

when you call the function from elsewhere, for example:

compute_bill(shopping_list)

that effective assigns:

food = shopping_list

as the function is called; the name “food” is not known outside the
function. And also, “food” does not have any value until you call the
function - it is the cal which defines food to be shopping_list (or
whatever other value you might choose to pass to the function).

Cheers,
Cameron Simpson cs@cskk.id.au

Thank you so much for replying.

How did it know to pick up the list from Shopping_list and not from anywhere else?

Your code as posted will not do that. It doesn’t pick up from shopping_list. You would have to put shopping_list as the function argument.

You have mentioned that your lesson says it is correct, but I don’t know what that means. Perhaps there’s a difference between what it is checking and what you’ve pasted? Or that it is only a syntax checker? Your code appears to have no syntax errors, but it will not print the shopping cost without some changes.

PART A
shopping_list = [“banana”, “orange”, “apple”]
stock = {“banana”: 6,“apple”: 0,“orange”: 32,“pear”: 15}
prices = {“banana”: 4,“apple”: 2,“orange”: 1.5,“pear”: 3}

PART B
def compute_bill(food):
total = 0
for i in food:
if stock[i] > 0:
total += prices[i]
stock[i] -= 1
return total

What I am trying to understand is - how does Part B of the code know to pull the data from Part A.

From what BowlOfRed said, I can understand I need to use

def compute_bill(food) as def compute_bill(shopping_list)

It will then work?

But the coding lesson in CodeAcademy says the who code above is correct with food as the definition of compute_bill.

l

No. Using a function requires two parts: one part where you create (define) the function and another part where you use (call) the function. Your definition part was okay, but the calling part was not.

On your most recent code you need to add a call to the function. Make a Part C like:

total_cost = compute_bill(shopping_list)
print(f"The cost for your list is {total_cost}")

This tells the program to use the function, and that the information in shopping_list should be provided as the first argument when it runs.

Hi Sajeev,

You asked:

“how does Part B of the code know to pull the data from Part A.”

Good question!

In your function, you have five variables:

food (parameter of the function)

total

i

stock

prices

The first three are called “local variables” because their name is

local to the inside of the function. They only exist while the

function is running.

The last two are called “global variables” because their name exists

outside of the function, they are global to the entire script. Every

function inside the script can see them.

Some languages need you, the programmer, to declare your variables

before you can use them. That tells the interpreter or the compiler

where the variable can be seen and which functions will recognise

that name.

Other languages, like Python, avoid (or mostly avoid) needing to use a

declaration. The interpreter can tell what sort of variable it is by

where it is used. The rules are:

  • if you assign a value to a name at the top level of the script,

    outside of any function, it is global variable;

  • if you assign a value to a name inside a function, then by

    default it is a local variable;

  • unless you declare it as global inside the function;

  • but if you just use a name without assigning to it, then

    Python assumes it is a global variable.

Examples:

# This is outside of any function.

variable = "a global variable"



def function1():

    # This is inside a function.

    # There is no assignment, so it is treated as global.

    print(variable)



def function2():

    # This is inside a function.

    # There is assignment, so it is treated as local.

    variable = "a local variable"

    print(variable)



function1()  # prints "a global variable"

function2()  # prints "a local variable"

These are called “scoping rules” and the we talk about the “scope” of

a variable, which parts of the program can see its value.

Python’s scoping rules are a bit more compilicated that I have said

above. We also have scopes for built-in names, class scopes, scopes for

functions nested inside of other functions, and comprehensions. Don’t

worry about all of those. The three important scopes are:

  • local inside a function;

  • global outside of any function or class;

  • builtins which are defined by the interpreter.

Sometimes we call this the LGB scoping rule.

Builtins include things like len, print, list etc. These are

technically variables just like the ones you create yourself.

Thank you! Sort of understood…but by the time I make it to the end I am confused :smiley:

So in this script:

a = 3
b = 6
c = 2

def my_funct(x, y):
return x + y

print (my_funct(a, b))

how does it know to associate x and y with a and b and not c ?

Because you passed (a,b) to my_funct. You did not pass c.

When you call a function is it a little like this:

my_funct(a,b)

    inside my_funct:
        x = a
        y = b
        ... do stuff ...

That is because the arguments to my_funct(a,b) are placed in the
my_funct parameters (x,y) in that order.

Cheers,
Cameron Simpson cs@cskk.id.au

So it associates 1st item with x, second with y and so on?

Yes, exactly. Those are “positional parameters”, where the association
is by position.

There are also keyword arguments, where the association is by name.

You can call my_funct like this:

my_funct(x=a, y=b):

and it is more overt. That’s uncommon but legal for positional
parameters. But more common with parameters which have defaults:

def my_funct(x, y, z=0, funny_mode=False):
    ...

This function requires you to call it with 2 parameters to set x and y.

You may also supply a third for z, but if you don’t z will be 0.

You may also supply a fourth parameter to set funny_mode, for example
to make it True. If you don’t, it will be False.

But to pass the fourth argument, you need to always pass the third:

my_funct(1, 2, 0, True)

Tedious, when you just want the default. Particularly if you don’t
know (or care) about the default for z. So you might instead go:

my_funct(1, 2, funny_mode=True)

which is using a keyword argument to set funny_mode; this allows you to
skip the “z” parameter.

Finally, once you get past 2 or 3 parameters, positional parameters
become clumsy and confusing. It is possibly to define a function with
keyword parameters which must be passed as keywords. In the above
example I’d usually define funny_mode like this:

def my_funct(x, y, z=0, *, funny_mode=False):

Here we always need to use the name “funny_mode” for the fourth
parameter.

Cheers,
Cameron Simpson cs@cskk.id.au

:smile:

Thank you so much!

I could only digest the first part though :smile: . Still a newbie!
The rest flew over my head :stuck_out_tongue:

Will try to understand more as i progress through the course.