On Mon, May 30, 2011 at 5:28 PM, Henry Olders <henry.old...@mcgill.ca> wrote:
>
> On 2011-05-29, at 4:30 , Henry Olders wrote:
>
>> I just spent a considerable amount of time and effort debugging a program. 
>> The made-up code snippet below illustrates the problem I encountered:
>>
>> def main():
>>       a = ['a list','with','three elements']
>>       print a
>>       print fnc1(a)
>>       print a
>>
>> def fnc1(b):
>>       return fnc2(b)
>>
>> def fnc2(c):
>>       c[1] = 'having'
>>       return c
>>
>> This is the output:
>> ['a list', 'with', 'three elements']
>> ['a list', 'having', 'three elements']
>> ['a list', 'having', 'three elements']
>>
>> I had expected the third print statement to give the same output as the 
>> first, but variable a had been changed by changing variable c in fnc2.
>>
>> It seems that in Python, a variable inside a function is global unless it's 
>> assigned. This rule has apparently been adopted in order to reduce clutter 
>> by not having to have global declarations all over the place.
>>
>> I would have thought that a function parameter would automatically be 
>> considered local to the function. It doesn't make sense to me to pass a 
>> global to a function as a parameter.
>>
>> One workaround is to call a function with a copy of the list, eg in fnc1 I 
>> would have the statement "return fnc2(b[:]". But this seems ugly.
>>
>> Are there others who feel as I do that a function parameter should always be 
>> local to the function? Or am I missing something here?
>>
>
> My thanks to all the people who responded - I've learned a lot. Sadly, I feel 
> that the main issue that I was trying to address, has not been dealt with. 
> Perhaps I didn't explain myself properly; if so, my apologies.
>
> I am trying to write python programs in a more-or-less functional programming 
> mode, ie functions without side effects (except for print statements, which 
> are very helpful for debugging). This is easiest when all variables declared 
> in functions are local in scope (it would also be nice if variables assigned 
> within certain constructs such as for loops and list comprehensions were 
> local to that construct, but I can live without  it).
>
> It appears, from my reading of the python documentation, that a deliberate 
> decision was made to have variables that are referenced but not assigned in a 
> function, have a global scope. I quote from the python FAQs: "In Python, 
> variables that are only referenced inside a function are implicitly global. 
> If a variable is assigned a new value anywhere within the function’s body, 
> it’s assumed to be a local. If a variable is ever assigned a new value inside 
> the function, the variable is implicitly local, and you need to explicitly 
> declare it as ‘global’.
> Though a bit surprising at first, a moment’s consideration explains this. On 
> one hand, requiring global for assigned variables provides a bar against 
> unintended side-effects. On the other hand, if global was required for all 
> global references, you’d be using global all the time. You’d have to declare 
> as global every reference to a built-in function or to a component of an 
> imported module. This clutter would defeat the usefulness of the global 
> declaration for identifying side-effects." 
> (http://docs.python.org/faq/programming.html)
>
> This suggests that the decision to make unassigned (ie "free" variables) have 
> a global scope, was made somewhat arbitrarily to  prevent clutter. But I 
> don't believe that the feared clutter would materialize. My understanding is 
> that when a variable is referenced, python first looks for it in the 
> function's namespace, then the module's, and finally the built-ins. So why 
> would it be necessary to declare references to built-ins as globals?
>
> What I would like is that the variables which are included in the function 
> definition's parameter list, would be always treated as local to that 
> function (and of course, accessible to nested functions) but NOT global 
> unless explicitly defined as global. This would prevent the sort of problems 
> that I encountered as described in my original post. I may be wrong here, but 
> it seems that the interpreter/compiler should be able to deal with this, 
> whether the parameter passing is by value, by reference, by object reference, 
> or something else. If variables are not assigned (or bound) at compile time, 
> but are included in the parameter list, then the binding can be made at 
> runtime.
> And I am NOT talking about variables that are only referenced in the body of 
> a function definition; I am talking about parameters (or arguments) in the 
> function's parameter list. As I stated before, there is no need to include a 
> global variable in a parameter list, and if you want to have an effect 
> outside of the function, that's what the return statement is for.
>
> I don't believe I'm the only person who thinks this way. Here is a quote from 
> wikipedia: "It is considered good programming practice to make the scope of 
> variables as narrow as feasible so that different parts of a program do not 
> accidentally interact with each other by modifying each other's variables. 
> Doing so also prevents action at a distance. Common techniques for doing so 
> are to have different sections of a program use different namespaces, or to 
> make individual variables "private" through either dynamic variable scoping 
> or lexical variable scoping." 
> (http://en.wikipedia.org/wiki/Variable_(programming)#Scope_and_extent).
>
> It also seems that other languages suitable for functional programming take 
> the approach I think python should use. Here is another quote from the 
> wikipedia entry for Common Lisp: "the use of lexical scope isolates program 
> modules from unwanted interactions. Due to their restricted visibility, 
> lexical variables are private. If one module A binds a lexical variable X, 
> and calls another module B, references to X in B will not accidentally 
> resolve to the X bound in A. B simply has no access to X. For situations in 
> which disciplined interactions through a variable are desirable, Common Lisp 
> provides special variables. Special variables allow for a module A to set up 
> a binding for a variable X which is visible to another module B, called from 
> A. Being able to do this is an advantage, and being able to prevent it from 
> happening is also an advantage; consequently, Common Lisp supports both 
> lexical and dynamic scope. 
> (http://en.wikipedia.org/wiki/Common_Lisp#Determiners_of_scope).
>
>
> If making python behave this way is impossible, then I will just have to live 
> with it. But if it's a question of "we've always done it this way", or, " why 
> change? I'm not bothered by it", then I will repeat my original question: Are 
> there others who feel as I do that a function parameter should always be 
> local to the function?
>
> And again, thank you all for taking the time to respond.
>
> Henry


Python doesn't have true globals. When we say "global" what we mean is
"module or built-in". Also, consider this code

from math import sin
def redundant_sin(x) :
    return sin(x)

In Python, everything is an object. That includes functions.  By your
definition, that function would either have to be written as
def redundant_sin(sin, x) :
and you would have to pass the function in every time you wanted to
call it or have a "global sin" declaration in your function. And you
would need to do that for every single function that you call in your
function body.





> --
> http://mail.python.org/mailman/listinfo/python-list
>
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to