Stocking Out - Print module


#1

When I try to print prices, I think my total is wrong. My food list has Apple and Banana. I am asking for the price of the same. It shoudl give me 4+2 = 6. But it prints out 4 ?

shopping_list = ["banana", "orange", "apple"]

stock = {
  "banana": 6,
  "apple": 0,
  "orange": 32,
  "pear": 15
}
    
prices = {
  "banana": 4,
  "apple": 2,
  "orange": 1.5,
  "pear": 3
}

# Write your code below!
def compute_bill(food):
  total = 0
  for item in food:
    if stock[item] >0:
      total += prices[item]
      stock[item] = stock[item] - 1
  return total

food=('apple','banana')
print compute_bill(food)

#2

I would suggest using the variable name, shopping_list instead of food so that it does not conflict with the local variable. Be sure to use a list object, not a tuple.

shopping_list = ['apple', 'banana']
print (compute_bill(shopping_list))

Note that apple has no stock, so the price is not added to the total.


#3

No reason to change food, there’s no case where the other one should be accessed. There should be no thought of what names are in “the other” place
Tuple has all the desired behaviour for that use, it’s fine (there’s a case for not using what’s not understood though)

It’s fair to point out that there’s no matching being done between names though, which might be the (unfounded) reason for choosing that name


#4

I keep confusing Python with JS in this respect.

Good point.


#5

Seems to me like JS would be the same, two pieces of code with no concern for each other’s local names


#6

I’ll have to run some tests but in my mind an array or object name is not shadowed inside a function.


#7

The scope of var is the function.
The value referred to has no effect on a variable’s scope


#8

This would seem to indicate that there is no shadowing of array objects.

function insert_to_list(list) {
  list.unshift(1, 3);
}

var list = [2,4,6,8];
insert_to_list(list);
console.log(list)

Output

[ 1, 3, 2, 4, 6, 8 ]

#9

There is, still referring to the same object though

You can rename list in the function for the same result


#10

Nothing is returned, but the global object is mutated. Wouldn’t that mean there is no shadowing? Or is it just the fact that an array is a reference object as opposed to a simple value?


#11

You’re just doing this…

a = []
b = a
b.append(1)
print(a)  # [1]

The object isn’t global, no object is. Variables are what are global, and those refer to objects


#12

Okay, but the variable list would still appear to be global inside the function. It is not a discrete variable in local scope. Only when we explicitly declare the variable does it shadow the global. This does not happen when simple values are passed. The parameter variable is implicitly a local variable.


#13

In the code you posted, it is:

And you can show this by reassigning it, the other one is unaffected

And you’d have complete chaos if this wasn’t the case, if global variables could take over local ones

Also, I doubt primitive types are passed by value (copied), large strings would make this very inefficient
The language implementation would be free to do whatever it wants though, because it wouldn’t be possible to tell the difference unless looking at object identity. This is one of the nice things about immutable values, there’s no reason to make copies because they won’t change.


#14
function insert_to_list(list) {
  var other = list;
  list.unshift(1, 3);
  return other
}

var list = [2,4,6,8];
console.log(insert_to_list(list));
console.log(list)
[ 1, 3, 2, 4, 6, 8 ]
[ 1, 3, 2, 4, 6, 8 ]

#15

You’re not making any copies.

If you had a copy, changing it would not change the original

If you don’t have a copy, then everything refers to the same array, or no array at all because there is no other


#16
function insert_to_list(list) {
  var other = list.slice();
  list.unshift(1, 3);
  return other
}

var list = [2,4,6,8];
console.log(insert_to_list(list));
console.log(list)
[ 2, 4, 6, 8 ]
[ 1, 3, 2, 4, 6, 8 ]

or,

function insert_to_list(list) {
  var other = list.slice();
  other.unshift(1, 3);
  return other;
}

var list = [2,4,6,8];
console.log(insert_to_list(list));
console.log(list)
[ 1, 3, 2, 4, 6, 8 ]
[ 2, 4, 6, 8 ]

#17

Here. With shadowing (creates separate function-local variable), and without:

function does_not_shadow() {
    a = 100
}

function does_shadow() {
    var a = 7
}


var a = 5
does_shadow()
console.log(a)     // 5
does_not_shadow()
console.log(a)     // 100

#18
function foo(a) {
    a = 100;
    return a;
}
a = 5
console.log(foo(a));
console.log(a);
100
5

On primitive values, even without var explicitly declared, the parameter shadows the global.


#19

My example uses primitive values, and there’s no shadowing there.
You have a function-local variable a

Otherwise you’d have stuff like this:

function f(x) {
    return x
}

f(3)  // does this cause x to be defined?
// no, because x is local to f

#20
function foo(a) {
    a = 100;
}
a = 5
console.log(foo(a));
console.log(a);
undefined
5

Were a to be an array, it would output in both statements. (not so)