1

I am trying to understand list comprehension by passing a list a of functions to act on list as shown in the code below.

def fun1(x):
  x.append(5)
  print(" In Fun 1:")
  print(x)
  return x 

def fun2(x):
  x.append(6)
  return x

def fun3(x):
  x.append(7)
  return x

int_list = [1, 2, 3, 4]
funs_family = (fun1, fun2, fun3)

new_list = [fun(int_list) for fun in funs_family ]
print(new_list)

I am expecting the result of the new_list to be

[1,2,3,4,5] [1,2,3,4,5,6] [1,2,3,4,5,6,7]

but the actual result is

[1,2,3,4,5,6,7] [1,2,3,4,5,6,7] [1,2,3,4,5,6,7] 

Can anyone explain why the actual result is different from expected result?

khelwood
  • 55,782
  • 14
  • 81
  • 108

4 Answers4

0

Return a new list in your fun_family methods and you will not see the issue:

def fun1(x): 
    x.append(5) 
    print("In Fun 1:") 
    print(x) 
    return list(x)

def fun2(x): 
    x.append(6) 
    return list(x)

def fun3(x): 
    x.append(7) 
    return list(x)

int_list = [1, 2, 3, 4] 
funs_family = (fun1, fun2, fun3)

new_list = [fun(int_list) for fun in funs_family]
print(new_list)
>> [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7]]
Alan Kavanagh
  • 9,425
  • 7
  • 41
  • 65
0

Here's a similar example for you to look at

int_list = [1, 2, 3, 4]
funs_family = (fun1, fun2, fun3)

new_list = [int_list for fun in funs_family]
int_list.append(5)
print(new_list)

Note that new_list does not depend on the functions at all, in fact they're never called. But what's printed is [1, 2, 3, 4, 5] three times. This is because the three lists inside new_list all point to the same list in memory. So when you change the original, it changes all of them.

Calvin Godfrey
  • 2,171
  • 1
  • 11
  • 27
0

Because you are appending to the list, it is actually the same object. At the end you are printing the exact same list three times. Instead, maybe what you want to do is create a new list within the function and add the int to it.

x = [1, 2, 3, 4]
x_copy = [i for i in x]
x_copy.append(5)
Chris Farr
  • 3,580
  • 1
  • 21
  • 24
0

Each of the functions returns x.

So

new_list = [fun(int_list) for fun in funs_family ] print(new_list)

… returns three copies of x, all of which are equal to [1,2,3,4,5,6,7] once the comprehension has finished.

What you want instead are copies of x, which you can get using [:]:

new_list = [fun(int_list)[:] for fun in funs_family ]
Rick Hitchcock
  • 35,202
  • 5
  • 48
  • 79