简体   繁体   English

有关可变范围规则的Python问题

[英]Python Question about Variable Scope Rules

This is a source code for Quicksort in Python I found on Wikipedia. 这是我在Wikipedia上找到的Python中Quicksort的源代码。

def pivot(v, left, right):
    i = left
    for j in range(left + 1, right + 1):
        if v[j] < v[left]:
            i += 1 # .. incrementa-se i
           v[i], v[j] = v[j], v[i]
    v[i], v[left] = v[left], v[i]
    return i

def qsort(v, left, right):
    if right > left:
        r = pivot(v, left, right)
        qsort(v, left, r - 1)
        qsort(v, r + 1, right)

a = [4,2,4,6,3,2,5,1,3]
qsort(a, 0, len(a)-1)
print a # prints [1, 2, 2, 3, 3, 4, 4, 5, 6]

My question is about scope. 我的问题是关于范围。 When I pass a as an argument in the example above, how can the function qsort possibly change the variable a in a global scope if it doesn't "call" 'global a'? 当我在上面的示例中将a作为参数传递时,如果函数qsort不“调用”“全局a”,它如何在全局范围内更改变量a I've been programming in python for 1 year and recently started learning C. Looks like I'm making some sort of confusion. 我从事python编程已有1年了,最近开始学习C。看起来我有点困惑。 thanks 谢谢

It doesn't rebind a / v , it merely mutates it. 它不会重新绑定 a / v ,它只是变异了。 You don't need to declare a name global if you're mutating the object it's bound to. 如果要更改绑定到的对象,则无需声明global名称。

In python a is passed by "alias" (See Jochen's comment below). 在python中,“别名”传递了a (请参见下面的Jochen注释)。 Therefore, Any modifications to v will be relflected in a . 因此,对v的任何修改都将在a反映出来。

EDIT: I fixed my wording thanks to the comments below. 编辑:由于下面的评论,我修正了我的措辞。

qsort receives a reference to the list object that is also bound to a . qsort接收至同样绑定到列表对象的引用a Within the function, the same object is bound to the local variable v , so any modifications made via v affect a as well. 在函数内,同一对象绑定到局部变量v ,因此通过v任何修改也会影响a

Read up about objects, references and variables for more information. 阅读有关对象,引用和变量的更多信息。

Yes, the rebind answer is a good one. 是的, 重新绑定答案是一个很好的答案。 It might be interesting for you -- since you start C, that you might want to familiarize yourself with the terms call-by-value and call-by-reference . 对于您来说可能很有趣-自从开始使用C以来,您可能想熟悉术语“ 按值 调用”和“按引用调用” Maybe knowing about those in advance will protect you from surprises: 也许提前知道这些会保护您免受意外的影响:

void callByValue(int number) {
    number = number + 1;
}

void callByReference(int *pnumber) {
    *pnumber = *pnumber + 1;
}

void main() {
    int x = 5;
    callByValue(x);
    // here, x is still 5

    int y = 5;
    callByReference(*y);
    // here, y is now 6.
}

Be it as it may, also in C you find, that the parameters number and pnumber will bind to the real variables x and y from the outside world. 无论如何 ,同样在C语言中,您会发现参数numberpnumber绑定到外部的实数变量xy In Python the fact that you have a list a = [4,2,4,6,3,2,5,1,3] will let you change that outside a by its inside name v . 在Python中,您拥有列表a = [4,2,4,6,3,2,5,1,3]的事实将使您可以通过内部名称v更改a之外a Just like pnumber allowed you that in C. In comparison a tuple would not have been mutable and would have been copied, ie a = (4,2,4,6,3,2,5,1,3) would not have worked. 就像pnumber允许您在C语言中进行操作。相比之下, 元组将不会是可变的,并且会被复制,即a = (4,2,4,6,3,2,5,1,3)不会起作用。 Just like in C the number is just a copy of x -- and therefore x does not change outside. 就像在C中一样, number只是x副本 -因此x不会在外部变化。

By the way, I suggest you skip C, but go right ahead and pick up some C++. 顺便说一句,我建议您跳过C,但是继续前进并选择一些C ++。 Some things are just nicer there. 有些东西在那里更好。 For example, you can do it here without the *pnumber all the time: 例如,您可以*pnumber在此处使用*pnumber来执行此操作:

void callByReferenceCPlusPlus(int &number) {
    number = number + 1;
}

void main() {
   int z = 5;
   callByReferenceCPlusPlus(z);
   // hooray, z is 6!
}

It might be a matter of taste, but it is really more straightforward, without thinking of the pointer-details all the time. 这可能是一个问题,但实际上更简单了,无需始终考虑指针的细节。 Really. 真。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM