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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With