为什么 Python for ... in ...: 语句中的元素使用 byValue 行为?

发布于 2024-10-02 19:13:56 字数 577 浏览 3 评论 0原文

我似乎无法在任何地方找到对此的解释...

假设我有一个向量 y 初始化为全零:

from numpy import *
y = zeros(5)

它也可以是一个普通的 python 数组,我认为这并不重要。

我注意到 for x in y: 语句的行为是它复制 y 中的每个元素,因此当您修改 x 时,它不会修改 y 。

for x in y:
    x = 1
print y

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

我的问题如下:为什么会这样?我认为在Python中一切都是byReference,并且很少有byValue传递?

我如何使用引用变量执行以下操作?执行以下操作似乎可行:

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

但根据我对 Python 的了解,这是错误的,我相信当我开始使用数千或数百万个值的向量时,它会很慢。

我还能做什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

胡大本事 2024-10-09 19:13:56

您可以将其替换

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

为:

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

如果 y 是 Python 序列(元组、列表、数组等)或 Numpy 数组,则

for x in y:

迭代 y,设置xy 中的每个元素。
如果元素是不可变对象,例如 strintfloat 或 Numpy 数字类型,
那么更改x 的值不会更改y 中的值。

如果元素是可变对象,例如 list,则改变 list 将影响 y

这样想:x“指向”一个对象:

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

当您编写赋值语句时:

x += 1

现在您正在重新分配x以“指向”另一个对象:

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

x---> o

另一方面,如果您使用 x.append(1) 来改变列表,那么
x 仍然指向同一个对象(例如列表),但您已经改变了该列表的内容。

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.

第几種人 2024-10-09 19:13:56

Python确实仅使用“引用”。但是 Python(和 Java,可能还有一些其他语言)中所谓的“引用”与“按引用传递”或“C++ 中的引用”不同。当您迭代类似 for i in iterable: 之类的内容时,i 指向当前项。但是,当您在循环中执行 i = ... 时,您将用新引用覆盖该引用,而不是替换所指向的对象。所以实际上,Python(以及提到的所有其他语言)都是按值传递的。除了这些值总是(某种)指针。

请注意,这不适用于 i.attr = ...!设置成员则不同,它是一个方法调用(对象的__dict__.__setitem__之一,.__setattr__.__setattribute__代码>据我所知)。因此,如果您在循环中执行i.some_member,您确实会更改可迭代的项目。另请注意,对于数字或字符串等不可变对象来说,这当然是没有意义的 - 您不可能更改它们。

如果您想直接更改例如列表,则需要使用索引(尽管您不需要 range(len(...)),您可以使用 enumerate(the_list)< /code> 并且您将获得索引当前项目)。还要考虑首先使用列表理解来生成您想要的值。

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.

何以畏孤独 2024-10-09 19:13:56

如果我错了,请有人纠正我,但Python中的整数类型是不可变的,这就是为什么当你对向量的元素之一执行某些操作时,你会得到一个新对象。我看了又看,但没有找到任何对这种预感的证实,但是当我尝试

>>> 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]]

并且我们知道列表是可变的时,我们得到了我们所期望的。

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.

情话已封尘 2024-10-09 19:13:56

我根本不明白该代码示例有什么错误 - 只要可以从 for 循环所在的范围访问 y ,一切都应该很好。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文