>>>>> Antoon Pardon <[EMAIL PROTECTED]> (AP) wrote: >AP> On 2006-07-05, Bruno Desthuilliers <[EMAIL PROTECTED]> wrote: >>> Antoon Pardon wrote: >>> (snip) >>>> Well no matter what explanation you give to it, and I understand how it >>>> works, >>> >>> I'm not sure of this.
>AP> Should I care about that? Yes, because as long as you don't understand it, you are in for unpleasant surprises. >>> It's not about "finding a name/identifier", it's about the difference >>> between (re)binding a name and mutating an object. >AP> The two don't contradict each other. Python has chosen that it won't >AP> rebind variables that are out of the local scope. So if the lefthand >AP> side of an assignment is a simple name it will only search in the >AP> local scope for that name. But if the lefthand side is more complicated >AP> if will also search the outerscopes for the name. No. It will always use the same search order. But a variable that is bound inside the function (with an asignment) and is not declared global, is in the local namespace. A variable that is not assigned to inside the function is not in the local namespace. An assignment to A[i] is not rebinding A, so it doesn't count to make the variable A local. >AP> Python could have chosen an approach with a "nested" keyword, to allow >AP> rebinding a name in an intermediate scope. It is not that big a deal >AP> that it hasn't, but I keep finding the result strange and somewhat >AP> counterintuitive. Maybe it would have been nice if variables could have been declared as nested, but I think it shows that nested variables have to be used with care, similar to globals. Especially not allowing rebinding in intermediate scopes is a sound principle (`Nested variables considered harmful'). If you need to modify the objects which are bound to names in intermediate scopes, use methods and give these objects as parameters. >AP> Let me explain why: >AP> Suppose someone is rather new of python and writes the following >AP> code, manipulating vectors: >AP> A = 10 * [0] >AP> def f(B): >AP> ... >AP> for i in xrange(10): >AP> A[i] += B[i] >AP> ... >AP> Then he hears about the vector and matrix modules that are around. >AP> So he rewrites his code naively as follows: >AP> A = NullVector(10): >AP> def f(B): >AP> ... >AP> A += B >AP> ... >AP> And it won't work. IMO the principle of least surprise here would >AP> be that it should work. Well, A = f(B) introduces a local variable A. Therefore also A = A+B. And therefore also A += B. The only way to have no surprises at all would be if local variables would have to be declared explicitly, like 'local A'. But that would break existing code. Or maybe the composite assignment operators should have been exempted. Too late now! You have the same problem with: A = [10] def inner(): A.append(2) works but A = [10] def inner(): A += [2] doesn't. The nasty thing in this example is that although A += [2] looks like a rebinding syntactically, semantically there is no rebinding done. I think the cleaner solution is (use parameters and don't rebind): def inner(A): A.append(2) -- Piet van Oostrum <[EMAIL PROTECTED]> URL: http://www.cs.uu.nl/~piet [PGP 8DAE142BE17999C4] Private email: [EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list