scope of function parameters (take two)

Dan Stromberg drsalists at gmail.com
Tue May 31 00:35:57 EDT 2011


On Mon, May 30, 2011 at 5:28 PM, Henry Olders <henry.olders at mcgill.ca>wrote:

> 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.
>

If you don't want any globals other than callables and modules and builtins,
then don't define any.  I normally code that way, other than an infrequent
(EG) HAVE_CSTRINGIO global or similar (which is module-global, not
program-global) - that is, for variables describing what sorts of optional
modules are available.

Be careful not to conflate global scoping or global lifetime, with
mutability or pure, side-effect-free functions (callables).  It sounds like
what you want is immutability and/or freedom from side effects, which is
found most often in (pure) functional languages - which is not what Python
is, nor does it attempt to be so.

In Python, and in many other languages, if you pass a scalar (or more
generally, an object of an immutable type) to a function, and then change
the scalar in that function, you only change the scalar within that
function, not within the caller.

However, if you pass an aggregate type like a list (array) or dictionary
(hash table), then the formal argument itself that you've passed is still
only changeable within that function, however what it points off at _is_
changeable via that formal argument.  This is of course because otherwise
passing a 1 gigabyte dictionary to a function would either have to copy the
whole dictionary, or implement some sort of Copy-on-Write semantics, or make
it somehow readonly.

If you need side effect-free functions in Python, you'd probably best copy
your aggregates, EG:

import copy

def main():
      a = ['a list','with','three elements']
      print a
      print fnc1(a)
      print a

def fnc1(b):
      b = copy.deepcopy(b)
      return fnc2(b)

def fnc2(c):
      c = copy.deepcopy(c)
      c[1] = 'having'
      return c

main()

Or use Haskell.  Please don't try to turn Python into Haskell.  Each has its
own interesting tradeoffs, and we don't really need two Pythons, and we
don't really need two Haskells.

HTH.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20110530/d0bf3213/attachment-0001.html>


More information about the Python-list mailing list