On Mon, May 30, 2011 at 5:28 PM, Henry Olders <[email protected]> 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