开发者

Why do elements in Python for ... in ...: statements use byValue behavior?

开发者 https://www.devze.com 2023-01-25 08:22 出处:网络
I can\'t seem to find an explanation anywhere for this... Suppose I have a vector y initialized to all zeroes:

I can't seem to find an explanation anywhere for this...

Suppose I have a vector y initialized to all zeroes:

from numpy import *
y = zeros(5)

It could also be a plain python array, I don't think it really matters.

I noticed that the behavior of the for x in y: statement is that it makes a copy of each element in y, thus when you modify x, it does not modify y.

for x in y:
    x = 1
print y

output : array([ 0.,  0.,  0.,  0.,  0.])

My question is the following : Why is that so? I thought in Python everything was all byReference and that there is very little byValue passing around?

How could I do the following, using referenced variables? Doing the following seems to work :

for i in range(len(y)):
    y[i] = 2*rand()-1

But from what I know about Python开发者_运维技巧, this is wrong and I believe it will be slow when I start using vectors of thousands or millions of values.

What else could I do?


You can replace this:

y = np.zeros(5)
for i in range(len(y)):
    y[i] = 2*rand()-1

with:

y=2*np.random.rand(5)-1

If y is a Python sequence (tuple, list, array, etc) or Numpy array,

for x in y:

iterates through y, setting x to each element in y. If the elements are immutable objects like str, int, float or a Numpy numeric type, then changing the value of x does not change the value in y.

If the elements are mutable objects, such as a list, then mutating the list will affect y.

Think of it this way: x is "pointing" to an object:

y---> [o----o----o----o]
            ^
            |
            x

When you write an assignment statement:

x += 1

Now you are reassigning x to "point" to a different object:

y---> [o----o----o----o]

x---> o

On the other hand, if you mutate a list with, say, x.append(1), then x still points to the same object (e.g. a list), but you've mutated the contents of that list.


Python does use "references" only. But what is called "reference" in Python (and Java, and propably a handful of other languages) is not like in "pass-by-reference" or "references in C++". When you iterate over something like for i in iterable:, i points to the current item. But when you do i = ... in the loop, you're overwriting that reference with a new one instead of replacing the object pointed to. So actually, Python (and all the other languages mentioned) are pass-by-value. Except that those values are always (kind of) pointers.

Note that this does not apply for i.attr = ...! Setting members is different, it's a method call (one of .__setitem__ of the object's __dict__, .__setattr__ or .__setattribute__ afaik). So if you did i.some_member in the loop, you would indeed alter the items of the iterable. Also note that this is of course moot with immutable objects like numbers or strings - you cannot possibly alter those.

If you want to alter e.g. a list directly, you need to use indices (although you shouldn't need range(len(...)), you can use enumerate(the_list) and you get indices and the current items). Also consider generating the values you want in the first place by using e.g. a list comprehension.


Please someone correct me if I am wrong, but the integer type in Python is not mutable and that is why when you perform some operation on one of the elements of the vector you get back a new object. I looked and looked but haven't found any confirmation of this hunch but when I try

>>> def zeros(length):
...     vector = []
...     for each in range(length):
...         vector.append([0])
...     return vector
... 
>>> zeros(8)
[[0], [0], [0], [0], [0], [0], [0], [0]]
>>> y = zeros(8)
>>> for x in y:
...     x[0] += 1
... 
>>> y
[[1], [1], [1], [1], [1], [1], [1], [1]]

and we know that lists are mutable we get what we expect.


I don't see how that code sample is wrong at all - as long as y is accessible from the scope that the for loop is in, all should be good.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号