Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python map function, passing by reference/value?

Tags:

python

I have a question about the map function in Python.

From what I understand, the function does not mutate the list it's operating on, but rather create a new one and return it. Is this correct ?

Additionally, I have the following piece of code

def reflect(p,dir):
  if(dir == 'X'):
    func = lambda (a,b) : (a * -1, b)
   else:
    func = lambda (a,b) : (a, b * -1)
  p = map(func,p)
  print 'got', p

points is an array of tuples such as: [(1, 1), (-1, 1), (-1, -1), (1, -1)]

If I call the above function in such a manner:

print points
reflect(points,'X')
print points

the list points does not change. Inside the function though, the print function properly prints what I want.

Could someone maybe point me in some direction where I could learn how all this passing by value / reference etc works in python, and how I could fix the above ? Or maybe I'm trying too hard to emulate Haskell in python...

Thanks

edit:

Say instead of p = map(func,p) I do

for i in range(len(p)):
  p[i] = func(p[i])

The value of the list is updated outside of the function, as if working by reference. Ugh, hope this is clear :S

like image 456
rafalio Avatar asked Aug 26 '11 10:08

rafalio


1 Answers

You misunderstand how references work in Python. Here, all names are references, there are no "values". Names are bound to objects. But = doesn't modify the object that's pointed to by the name — it rebinds the name to a different object:

x = 42
y = x
# now:
# 'is' is a identity operator — it checks whether two names point to the
# exact same object
print x is y # => True
print x, y   # 42 42
y = 69
# now y has been rebound, but that does not change the '42' object, nor rebinds x
print x is y # => False
print x, y   # 42 69

To modify the object itself, it needs to be mutable — i.e. expose members that mutate it or have a modifiable dict. The same thing as above happens when you rebind p — it doesn't touch points at all, it simply modifies the meaning of local p name.

If you want to simulate C++-like references, you need to encapsulate the object into a mutable container, e.g. a list.

reflect([points], 'X')

# inside reflect:
p[0] = ...

But you shouldn't, at least in this case — you should just return the new object instead.

points = reflect(points, 'X')

# inside reflect, instead of p = ...
return map(func, p)

Well, now that I think about it, you can also do

p[:] = map(func, p)

But again, returning new object is usually better.

like image 180
Cat Plus Plus Avatar answered Nov 02 '22 15:11

Cat Plus Plus