开发者

Python Question about Variable Scope Rules

开发者 https://www.devze.com 2023-02-10 10:54 出处:网络
This is a source code for Quicksort in Python I found on Wikipedia. def pivot(v, left, r开发者_运维百科ight):

This is a source code for Quicksort in Python I found on Wikipedia.

def pivot(v, left, r开发者_运维百科ight):
    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'? I've been programming in python for 1 year and recently started learning C. Looks like I'm making some sort of confusion. thanks


It doesn't rebind a/v, it merely mutates it. You don't need to declare a name global if you're mutating the object it's bound to.


In python a is passed by "alias" (See Jochen's comment below). Therefore, Any modifications to v will be relflected in 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. Within the function, the same object is bound to the local variable v, so any modifications made via v affect a as well.

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. 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. 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. Just like pnumber allowed you that in C. In comparison a tuple would not have been mutable and would have been copied, i.e. a = (4,2,4,6,3,2,5,1,3) would not have worked. Just like in C the number is just a copy of x -- and therefore x does not change outside.

By the way, I suggest you skip C, but go right ahead and pick up some C++. Some things are just nicer there. For example, you can do it here without the *pnumber all the time:

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.

0

精彩评论

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