What am I doing wrong:
def total(numbers):
result = 0
for item in numbers:
item + result
return result
What am I doing wrong:
def total(numbers):
result = 0
for item in numbers:
item + result
return result
Item + result is not a legal operation.
If you meant to increment result variable then you need to check the item + result and redo it so it reflects something like
x += y
so that when you return result its value is updated.
a = 0
b = 1
a = a + b
That is one example. You can also just do.
a = 0
b = 1
a += b
Hey guys, I’m really confused on the whole for loops being used in-conjunction with lists, don’t really feel previous lessons have explained it enough for me to understand. I was wondering if anyone could help provide an idiot proof explanation!!! Here is the code I have used:
n = [5,8,2]
def total(numbers):
for n in numbers:
result = 0
result += n
return result
print total(n)
If I do the following then I get a result of 2:
result += n
return result
When I run this code I get the value 5, and I don’t know why, however if I remove the function and just use a for loop like so:
n = [5,8,2]
for numbers in n:
result = 0
result += numbers
print result
The code only prints out the last value in the list ( I know that the word numbers and n are swapped between the first and second example, and that the result += changes between n and numbers also, this is because if I don’t then on the second example I get an error saying int object is not iterable, I don’t entirely know what this means either.)
if I indent the print like so:
result += numbers
print result
Then it ends up printing all 3 numbers ie:
5
8
2
If anyone could help explain what is happening and what I am doing wrong, I would me much grateful!!!
Please have a look at How do I format code in my posts? which explains how to keep the code formatting and for Python the indentation which is very important.
If I’m not mistaken your first code has the return
statement inside the loop. As soon as return
is executed the function stops at the point and returns the result to the original caller. If it’s in a loop this means your loop probably finishes too soon.
This is also what makes your print
repeat three times. If you review the steps your loop takes you can probably also see why the output is 5
, 8
, 2
instead of the expected total.
Try playing around this until it makes sense .
But I don’t know what steps my for loop takes, to get the result that it does, which is why I was wondering if anyone could help provide an explanation as to what I am doing wrong, or how to do it correctly?
I thought I had, your problem is that you return
too early (and reset your counter too). Things inside the loop will run on every iteration of the loop. Think very carefully about what you actually want to repeat in this loop.
Can you explain what the error message object is not iterable?
Can you also explain if below is done:
my_list = [1,9,3,8,5,7]
total = 0
for number in my_list:
total += number
print total
Then it prints out:
1
10
13
21
26
33
but if the print statement is not indented, the same as previous line above, it just prints out 33, is it because if its indented, it’s saying for every item in the list, add that item to total then print the current total, and repeat this process, but if that is correct, if the print statement is unindented it just prints the whole total: 33, can you explain this please?
If I do the following:
my_list = [1,9,3,8,5,7]
def add_my_list(total):
total = 0
for number in my_list:
total += number
return total
print add_my_list(total)
Then I get an error saying total is not defined, but if I do the below, then I get 33? why if I declare total = 0
, outside the function it works, but if I don’t, I get an error?
my_list = [1,9,3,8,5,7]
total = 0
def add_my_list(total):
for number in my_list:
total += number
return total
print add_my_list(total)
The first code is correct, except you then try to use total
outside the function as well:
print add_my_list(total)
total
has a local scope (only exists within the function)
when you call the function, I think you want to provide my_list
as argument
about the second code sample: bad idea, you have a global total, which means multiple function calls will add to the total of earlier function calls
Surely if print add_my_list(total)
is carried out it is part of the function, as it is set to zero below the line def add_my_list
? When I do print add_my_list(my_list)
it does return 33 (which is correct), but how why does this work if when I created the function I used the argument total ie, def add_my_list(total)
?
no, functions are a set of instructions which are executed later. Kind of like a todo-list, you can make a todo list (defining functions), but actually executing the tasks on the todo-list (calling functions) can happen later
parameters like total here:
def add_my_list(total):
act as placeholder until the parameters receive their actual values from arguments at function call.
So I understand that a function is a way of creating a to-do list, which then can be called later, but if I understand what you’re saying correctly about place holders , in the example: def add_my_list(total)
total is just a placeholder value, which means it hasn’t actually been defined? If that is the case then how come, when you type def add_my_list(total)
the total is a place holder for an argument, and you then set it to zero ie:
def add_my_list(tottal)
total = 0
how come if you then were to call the function with total as the argument it wont work?
ie: print add_my_list(total)
since you have defined total by setting it to zero and then incorporating it into a for loop, add if total is just a place holder, what’s the point in using place holder’s if you can just use the name of the variable you want to pass as the argument?
ie:
my_list = [1,9,3,8,5,7]
def add_my_list(my_list):
total = 0
for number in my_list:
total += number
return total
print add_my_list(my_list)
Which still works and prints the correct result 33.
Think of it more like this…
def add_my_list(a_list): # a_list is the parameter
total = 0
for number in a_list:
total += number
return total
my_list = [1,9,3,8,5,7]
print add_my_list(my_list) # my_list is the argument
Parameters are names in the local namespace that refer to positional arguments. One parameter, one argument. The argument is an object, the parameter is the name that object will be known by in local scope. It gets messy when we give the argument (object) and the parameter the same name, especially if we don’t fully understand scope.
It would appear in this conversation that one is clear on the scope in which total
is defined (as well as a_list
) which explains why we cannot access it outside of the function.
What is wrong with using the same name for the parameter and argument? Surely it just makes things easier to follow especially if you’re looking at someone else’s code? I am confused in what you mean when you say ‘the scope in which total
is defined’ I understand that in order to pass an argument, within a function you need to declare one ie def add_my_list(total
where total
is just a place holder, but I still don’t understand why if when total
is set to zero it hasn’t been defined? and why you can’t use my_list
as the argument in the function?
It doesn’t make sense, and it does not make it easier to read. Remember that this function is a utility that can be called from anywhere in the program on any list object. Keep the names to the objects discrete, and the names of the parameters generic.
Parameters are not placeholders. They are locally defined variables that indicate a required positional argument.
In what scope is target
defined?
But it is used as the argument (the function call).
def foo (variable): # parameter is a local generic name
pass
print (foo(object)) # argument is an object in outer scope
It would appear in this conversation that one is clear on the scope in which
total
is defined (as well asa_list
) which explains why we cannot access it outside of the function.
In your previous reply you mentioned the above, and in your last reply you said:
In what scope is
target
defined?
But I don’t know what a scope is, so I am not clear on how it is defined, if you could please explain what you mean by scope, so I can understand what you’re trying to say. I would also like to ask in what way is it not clear to use the same name for the argument and parameter. When I do the following:
list_1 =[1, 2, 3] def add_list(list_1): total = 0 for i in list_1: total += i return total print add_list(list_1)
print times_list(list_1) def times_list(list_1): total = 0 for i in list_1: total += i *2 return total print times_list(list_1)
Both do as expected ie the first prints 6 and the second 12. I am also confused about when using the for loop to total += i
, if I do += [i]
or += list_1
I get the following error: unsupported operand type(s) for +=: ‘int’ and ‘list’, if I do: += list_1[i]
I get: list index out of range, but if you compare that to using the range method, the range method only works when doing += numbers [i]
. Can you kindly explain what these mean and why I get them, and why when using the range method the +=
is different? The last question I have is when using the range method I’ve noticed that if I do either for i in range(len(numbers)):
or for i in range(0,len(numbers)):
I get the same outcome, but the solution writes it as the former, why is this?
There is some mention of Scope in the Learn Python 3 course, and another more in depth look at in the Learn Intermediate Python 3 course. Are you a Pro or Student subscriber? If so, track down that unit in the course.
Briefly, there are four kinds of scope in Python.
From the bottom, look up. The scopes above are accessible to the scopes below, but not the other way around (without some help). As we can see, all scopes are accessible from local
scope. That is the scope, or namespace inside a function.
def foo():
# local scope
pass
When a variable is declared within the function, it can only be accessed from within that function. Any variables outside of the function remain accessible from within it.
def bar():
# enclosing scope
pass
def foo():
# local scope
pass
Variables declared in bar
are accessible to foo
but not the other way around. From the point of view of foo
, the variables in bar
are seen as non-local. In order for foo
to be able to mutate those variables it will require a binding declaration…
def bar():
# enclosing scope
b = 40
def foo():
# local scope
nonlocal b
b += 2
Outside of a function we are in global
scope. From this namespace we can access (call) all direct functions, but none of the enclosed functions. We can call bar()
, but not foo()
. All global variables can be accessed from anywhere except the built-in
namespace. If our function is expected to mutate a global variable, then just as we declared b
to be non-local in foo()
, we would need to declare a binding.
a = 73
def bar():
global a
a -= 31
Lastly we have the built-in namespace which is where Python resides.
Anyway, I hope you can track down that unit and give it a read.
As for your other questions,
+= i
and
+= [i]
are two completely different operations. The first one can only be performed on a static number, such as,
b = 40
b += i
which will increase b
by i
.
b = [40]
b += [I]
will append i
to the list, not add it to 40. (see list.extend()).
The multiplication function implies we are to double each value in the list, which does not involve keeping a running tally (so no total
).
for x in list_1:
won’t work since we cannot mutate the list.
for i in range(len(list_1):
list_1[i] *= 2
will work since we are iterating the range, not the list. Rule of thumb, never mutate a list you are iterating. Python simply won’t allow it.
Notice we touch on your range question, above. When the start index is omitted, Python defaults to zero, so whether we include the 0
or not, it is still the starting value. We need that positional argument so that we can start wherever we wish.
for i in range(3, int(n ** 0.5) + 1, 2):
Above the start value is 3
, the end value is int(n ** 0.5) + 1, and the step, or *stride* value is
2`. Recall that a range does not include the uppermost value.
Of note
+=
can also be used on strings to perform in-place concatenation (much like the list concatenates with another list).
*=
can also be used on strings to perform repetition.
>>> a = '*'
>>> a *= 8
>>> a
'********'
>>>
and similarly, on lists…
>>> a = ['0']
>>> a *= 8
>>> a
['0', '0', '0', '0', '0', '0', '0', '0']
>>>
The other arithmetic assignment operators can only be used on numbers or bits. We cannot subtract from a string or list object. Neither can we divide, etc.
Lastly, with regard to range, we can set the direction in reverse by starting from the right side and ending on the left (remember the last value is excluded so it you wish to end on 0
, it must be set to -1
) and using a negative stride value…
>>> list(range(10, -1, -1))
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>>