0

I created a function and I want to append a number to the list:

def num(f):
    list1.append(i)
    return list1

list1 = []
i = 1
print "Now list1 is %s and i is %d" % (list1, i)    
num(list1)
i += 1
print "Now list1 is %s and i is %d" % (list1, i)
num(list1)
i += 1
print "Now list1 is %s and i is %d" % (list1, i)
print list1
print i 

Why do I have to return a function? It works with and without the return.

I was told that the function returns None if no return-statement was reached. But the function, mentioned above, works even if I don't type this return-statement.

Valijon
  • 12,667
  • 4
  • 34
  • 67
  • You didn't get the idea of a function yet. Values enter a function with the parameters and leave it with `return`. Don't use global variables in your function, so in this case it means don't use `list1` in the function, That line should be `f.append(i)`. Of course `i` should be a parameter of that function too. – Matthias Feb 13 '16 at 11:11
  • This **is not** "returning a function". It is returning a **value from** the function. – Karl Knechtel Sep 11 '22 at 07:17

3 Answers3

2

In the provided example, returning a value is unnecessary because the append list method, and by extension your function as well, operates by side effect. Functions called only for side effects are not functions in the mathematical sense (mappings of domain values to codomain values), they serve to change state of mutable objects, in this case by appending an item to a list. While such functions can return a value, Python has a convention that functions invoked purely for side effect, such as list.append, only return None, denoting no useful return value.

If your function were side-effect-free, you would need to have a return statement for it to be useful at all. As an example, compare:

def add(a, b):
    return a + b

...with the syntactically just as legal, but pretty useless:

def add(a, b):
    a + b
    # without a return statement, None is returned,
    # and the calculated sum discarded
user4815162342
  • 141,790
  • 18
  • 296
  • 355
2

I see you don't understand how functions work, so I added comments to your code to explain a little, but I suggest you to read Python tutorial about functions and wiki article further to gain understanding.

Also, I omitted many details not to overload the explanation. Important thing is there're immutable (i.e. integer, i in your example) and mutable (i.e. list, list1 in your example) types in Python and depending on this the behavior will be different.

def num(f):
    #Here the argument you pass to the function is named 'f'
    #and you don't use it

    #The next line uses 'list1', that is defined in global scope
    #since you didn't redefined this name inside the function
    #Variable 'i' is also the one in global scope for same reasons
    list1.append(i)

    #Here you return 'list1', though you don't use this value
    #further in your program. Indeed, you would not write a return
    #statement the function would return 'None' as the return value
    return list1

#Here you define 'list1' in global scope, and it will be used 
#inside 'num' function, even without providing it as the argument
list1 = []

#Here you define 'i' in global scope, and it will be used 
#inside 'num' function
i = 1

#Here you print 'i' and 'list' from global scope
print "Now list1 is %s and i is %d" % (list1, i)   

#Here you call 'num' function and 'list1' provided as argument
#is assigned to 'f' inside the function, but you didn't used it and
#and instead used names from global scope - that's why it works in
#this way (however it is wrong use of function)
#With 'list1.append(i)' the 'list1' is modified in place so it
#doesn't matter if it is returned or not
num(list1)

#As to 'num' return value, it will be the same value as 'list1', but
#you don't use it here, to use it it needs to be assigned with '=' to
#some variable, i.e. 'list2=num(list1)', though in fact 'list1' and 'list2'
#will be the same all the time due to Python internals, but let's skip the
#details of this.

#You can see that the value returned is not 'None' - add the 
#following line here:
print(num(list1))
#and run your program, the output will show you that it's a list returned.
#then remove the 'return' line in your function and run program again
#the output here will show, that is's 'None' that was returned.

So to fix the obvious mistake in the function:

def num(f):
    f.append(i)
    return f

but i is still used from global scope and not passed as argument, so even better:

 def num(f_var,i_var):
    f_var.append(i_var)
    return f_var

Though the list will be modified inplace and you don't really have to return it in you particular example, so:

 def num(f_var,i_var):
    f_var.append(i_var)

 list1=[]
 i=1

 num(list1,i)

will work too.

Nikita
  • 6,101
  • 2
  • 26
  • 44
1

You don't use the return value, so it makes no difference, what you return. You also don't use the argument. You probably wanted to write

def append_num(f, i):
    f.append(i)

and use two arguments:

append_num(list1, i)
Daniel
  • 42,087
  • 4
  • 55
  • 81