Fwd: Python-list digest, Vol 1 #17390 - 13 msgs

Rob Hunter rhunter007 at yahoo.com
Wed Sep 17 00:24:21 EDT 2003


> > From: anton at vredegoor.doge.nl (Anton
> Vredegoor)
> > Subject: Re: Is there "let binding" in
> Python?
> > Date: Wed, 17 Sep 2003 00:41:53 +0200
> > Organization: Hobby Computer Club News
> Network
> > To: python-list at python.org
> >


> > What's wrong with dynamic scoping? Anyway,
> Python hasn't corrected
> > this "mistake", 

Yes they have.  Python now has static scoping.  I
think that this shows it:

def test():
    x = 100
    f = lambda arg: arg * x
    def other_func():
        x = 1
        return f(x)
    print other_func()

test()

So what does this print?  Well, if the function f
used names in the environment in which it's
called, then x would be one and so we'd see the
answer as 1*1 = 1. That's dynamic scoping.  With
static scoping, function f's body uses the
environment that existed when it was created. 
Thus, x is bound to 100, and so we get the answer
100.  And 100 is what you actually get in Python.

My example from before was poor.  I was merely
saying the IMO, a downside of mutation/assignment
is that it kind of reintroduces the problems you
get from dynamic scoping.  This is certainly
debatable, but see for example the thread that
was just started on "scoping with lambda in
loops"...yet another person confused by
mutation/assignment.  And, IMO, the problem is
not with the person.


see following code (I vaguely
> remember *something*
> > about this was fixed, and while I don't know
> exactly what it was, I'm
> > reasonably sure it wasn't what you write
> about above, since that still
> > functions the way you think is bad)
> >
> > import sys
> >
> > def test():
> >     L =[]
> >     for i in range(10):
> >         f = lambda : sys.stdout.write("%s"
> %i)
> >         g = lambda i=i :
> sys.stdout.write("%s" %i)
> >         L.append((f,g))
> >     for x,y in L:
> >         x()
> >         y()
> >     print
> >
> > if __name__=='__main__':
> >     test()
> >
> > # output : 90919293949596979899
> >

So I apologize but I'm still very new at python,
so I don't really understand this program, but I
think what you are just showing me is that using
mutation/assignment you effectively get dynamic
scoping.  Which is what I'm saying.  But, I'll
concede that assignment isn't all bad.  Like
whatever you are showing here I'm sure is fine.

So is dynamic scoping bad?  Yes.  Most certainly.
 In the above example it perhaps isn't so clear
whether or not the program should print 1 or 100.
 But consider this (quite realistic, though
simplified) example:  I write a module which
provides a function circle_maker(x,y).  If you
give circle_maker x and y coordinates, it returns
a function which takes a radius, and draws a
circle with that radius at (x,y).

Eg, if I want to draw 3 circles each centered at
(1,2) with radii of 1, 2, and 3, I could write:

c = circle_maker(1,2)
c(1)
c(2)
c(3)

But now assume the defintion of circle_maker is
something like:

def circle_maker(x,y):
  ...
  x = --something complicated--
  ...
  return lambda radius: ... x ...

That is, our return function (which we bound to c
in this example), makes reference to 
the variable x.

But now, if I have dynamic scoping and if I want
to use circle_maker I better make darn sure that
I don't have an x in the environment when I call
it.  Or else that value of x will shadow the
intended value of x I had when I defined it in
circle_maker.

In short, if you have dynamic scoping, and you
use "other people's functions", then you have to
potentially know about all the variable names
they chose so you don't use those variables too. 
This is a nightmare when it comes to libraries.

Rob

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com





More information about the Python-list mailing list