Python Question about Variable Scope Rules
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.
精彩评论