459,677 Members | 1,128 Online
Need help? Post your question and get tips & solutions from a community of 459,677 IT Pros & Developers. It's quick & easy.

# loop scope

 P: n/a a=[1,2,3] for p in a: print p 1 2 3 p 3 My naive expectation was that p would be 'not defined' from outside the loop. I know this is not news. In fact I had come across some discussion of this fact, but apparently didn't register it. As I got myself surprised by it - specifically in the context of list comps, where I think it is particularly surprising: b=[4,5,6] [t*2 for t in b] [8, 10, 12] t 6 Is this anywhere useful, or more of an artifact? Art Jul 18 '05 #1
33 Replies

 P: n/a "Arthur" wrote in message news:f8********************************@4ax.com...a=[1,2,3] for p in a: print p 1 2 3 p 3 My naive expectation was that p would be 'not defined' from outside the loop. I know this is not news. In fact I had come across some discussion of this fact, but apparently didn't register it. As I got myself surprised by it - specifically in the context of list comps, where I think it is particularly surprising: b=[4,5,6] [t*2 for t in b] [8, 10, 12] t 6 Is this anywhere useful, or more of an artifact? For loops with a break statement, the value of the loop index when the break occurs may be the answer sought or needed to calculate it. For list comps which cannot have break, it is an artifact which may disappear in 2.4. Terry J. Reedy Jul 18 '05 #2

 P: n/a On Thu, 11 Mar 2004 21:08:09 GMT, Arthur wrote: a=[1,2,3] for p in a: print p123 p3My naive expectation was that p would be 'not defined' from outsidethe loop.I know this is not news.In fact I had come across some discussion of this fact, but apparentlydidn't register it.As I got myself surprised by it - specifically in the context of listcomps, where I think it is particularly surprising: b=[4,5,6] [t*2 for t in b][8, 10, 12] t6Is this anywhere useful, or more of an artifact? Scopes are defined by the boundaries of functions, classes and modules, not for loops. This is essential, or you would have to declare global variables inside most for loops. For a good, up-to-date discussion of scopes, see Learning Python, Ch. 13 Scopes and Arguments, and p.337 - Namespaces: The Whole Story. Be sure to get the 2nd edition. The scope rules have changed significantly since the first edition. -- Dave Jul 18 '05 #3

 P: n/a Terry Reedy wrote: For loops with a break statement, the value of the loop index when the break occurs may be the answer sought or needed to calculate it. For list comps which cannot have break, it is an artifact which may disappear in 2.4. If I understand you, I don't think I like this idea. It adds complexity to the mental model of a loop. "The loop variable disappears when the loop ends unless the loop contains a break". In my opinion, Python should pick a model and stick to it. Loop variables are either ordinary variables that exist until you explicitly delete them, or they are special variables that automagically disappear at the end of the loop. I vote for the first one. -- Steven D'Aprano Jul 18 '05 #4

 P: n/a Quoth us**@domain.invalid: | Terry Reedy wrote: | |> For loops with a break statement, the value of the loop index when the |> break occurs may be the answer sought or needed to calculate it. For list |> comps which cannot have break, it is an artifact which may disappear in |> 2.4. | | If I understand you, I don't think I like this idea. It | adds complexity to the mental model of a loop. "The | loop variable disappears when the loop ends unless the | loop contains a break". | | In my opinion, Python should pick a model and stick to | it. Loop variables are either ordinary variables that | exist until you explicitly delete them, or they are | special variables that automagically disappear at the | end of the loop. I vote for the first one. That makes sense to me, but I read "For list comps" as "For list comprehensions (but not conventional loops.)" List comprehensions shouldn't need to have every side effect of the equivalent loop. Donn Cave, do**@drizzle.com Jul 18 '05 #5

 P: n/a On Thu, 11 Mar 2004 17:54:56 -0700, David MacQuigg wrote:> b=[4,5,6]> [t*2 for t in b][8, 10, 12]> t6Is this anywhere useful, or more of an artifact?Scopes are defined by the boundaries of functions, classes andmodules, not for loops. This is essential, or you would have todeclare global variables inside most for loops. I am not following this argument. The surprise, specifically, is that I don't think of myself as having declared "t" as a variable. it is don't magically, as a placeholder and for a very specific purpose. So I would expect it to go away outside of the " [ " and " ] " by equal and opposite magic. I ran into the issue while playing at the prompt. Running the same statement I had run previously gave me a different result than before. Surprising. Yes I had tested a list comp, in between. Because I have been around the language for some time, and have my ear to the ground, it didn't take me long to understand what was happening. Flabbergasted, rather than surprised, might have otherwise been the reaction. Art Jul 18 '05 #6

 P: n/a wrote in message news:40**************@domain.invalid... Terry Reedy wrote: For list comps which cannot have break, it is an artifact which may disappear in 2.4. If I understand you, I don't think you did. The 'may' only applies to list comprehensions. The discussion last fall was whether the index names(s) within a list comprehension should be bound outside (after) the list comp. It is something of an accident of the current implementation that they are. The issue arose in the development of generator comprehensions, in which it was clear that the within-generator variables would *not* be bound outside of the produced generator. Bret Cannon's summary http://www.python.org/dev/summary/20...-older-brother is this: --------------- A quick example is: (x for x in range(10) if x%2) returns an iterator that returns the odd numbers from 0 to 10. This make list comprehensions just syntactic sugar for passing a generator expression to list() (note how extra parentheses are not needed): list(x for x in range(10) is x%2) Having list comprehensions defined this way also takes away the dangling item variable for the 'for' loop. Using that dangling variable is now discouraged and will be made illegal at some point. ---------------- Terry J. Reedy Jul 18 '05 #7

 P: n/a >>>>> "Arthur" == Arthur writes: Arthur> I am not following this argument. The surprise, specifically, Arthur> is that I don't think of myself as having declared "t" as a Arthur> variable. it is don't magically, as a placeholder and for a Arthur> very specific purpose. So I would expect it to go away outside Arthur> of the " [ " and " ] " by equal and opposite magic. I remember I've read that this more proper scoping for list comprehension will take effect in a future version of Python. Regards, Isaac. Jul 18 '05 #8

 P: n/a On Fri, 12 Mar 2004 14:06:38 GMT, Arthur wrote: On Thu, 11 Mar 2004 17:54:56 -0700, David MacQuigg wrote: Scopes are defined by the boundaries of functions, classes andmodules, not for loops. This is essential, or you would have todeclare global variables inside most for loops.I am not following this argument. The surprise, specifically, isthat I don't think of myself as having declared "t" as a variable. itis don't magically, as a placeholder and for a very specific purpose.So I would expect it to go away outside of the " [ " and " ] " byequal and opposite magic. The "declarations" are automatic, whenever you *use* a variable. I would *not* expect temporary variables in a loop to go away outside of the loop. It's just another variable in the current namespace. I think I may have misunderstood your original question. The title of the thread is 'loop scope', but your question seems to be specifically on the loop iteration variable 't'. Just think of it as a normal variable in the current local scope. The one exception I can think of is what Terry Reedy mentioned - the iteration variable in a list comprehension. In some future optimization, they may neglect to save that variable. I hope they don't do that (even though it really has no use). I just like the consistency we now have in treatment of all local variables. -- Dave Jul 18 '05 #9

 P: n/a In article , Arthur wrote:On Thu, 11 Mar 2004 17:54:56 -0700, David MacQuigg wrote:Scopes are defined by the boundaries of functions, classes andmodules, not for loops. This is essential, or you would have todeclare global variables inside most for loops.I am not following this argument. The surprise, specifically, isthat I don't think of myself as having declared "t" as a variable. itis don't magically, as a placeholder and for a very specific purpose.So I would expect it to go away outside of the " [ " and " ] " byequal and opposite magic. Well, you don't declare variables in Python. You use names to refer to objects. Python 2.4 may give each list comprehension its own namespace, but for now names used in a list comp. are used just as they would be in any other statement. Regards. Mel. Jul 18 '05 #10

 P: n/a David MacQuigg writes: On Fri, 12 Mar 2004 14:06:38 GMT, Arthur wrote:On Thu, 11 Mar 2004 17:54:56 -0700, David MacQuigg wrote:Scopes are defined by the boundaries of functions, classes andmodules, not for loops. This is essential, or you would have todeclare global variables inside most for loops. The one exception I can think of is what Terry Reedy mentioned - the iteration variable in a list comprehension. In some future optimization, they may neglect to save that variable. I hope they don't do that (even though it really has no use). I just like the consistency we now have in treatment of all local variables. You can maintain that consistency by extending the list of "boundaries" which define scopes; you already mentioned classes, functions and modules ... now simply add list comprehensions (or loops), and you will maintain perfect consistency of treatment of local variables, without leaking variables out of list comprehensions (or loops). Jul 18 '05 #11

 P: n/a On 12 Mar 2004 17:13:19 +0100, Jacek Generowicz wrote: David MacQuigg writes: On Fri, 12 Mar 2004 14:06:38 GMT, Arthur wrote: >On Thu, 11 Mar 2004 17:54:56 -0700, David MacQuigg >wrote: >>Scopes are defined by the boundaries of functions, classes and >>modules, not for loops. This is essential, or you would have to >>declare global variables inside most for loops. The one exception I can think of is what Terry Reedy mentioned - the iteration variable in a list comprehension. In some future optimization, they may neglect to save that variable. I hope they don't do that (even though it really has no use). I just like the consistency we now have in treatment of all local variables.You can maintain that consistency by extending the list of"boundaries" which define scopes; you already mentioned classes,functions and modules ... now simply add list comprehensions (orloops), and you will maintain perfect consistency of treatment oflocal variables, without leaking variables out of list comprehensions(or loops). I think the current design of Python is the right compromise between narrow scopes that avoid conflicts between identical names and broad scopes that minimize the need for global declarations. Imagine having to declare globals inside every loop that needed to set some value outside of its own tiny little scope. -- Dave Jul 18 '05 #12

 P: n/a "David MacQuigg" wrote in message news:ut********************************@4ax.com... The one exception I can think of is what Terry Reedy mentioned - the iteration variable in a list comprehension. In some future optimization, they may neglect to save that variable. I hope they don't do that (even though it really has no use). I just like the consistency we now have in treatment of all local variables. Please see other post. In the future, the consisitency will be with generator comprehensions, where the loop variable is clearly encapsulated inside the induced generator function. Terry J. Reedy Jul 18 '05 #13

 P: n/a Jacek Generowicz wrote: now simply add list comprehensions (or loops), and you will maintain perfect consistency of treatment of local variables, It wouldn't do to make the whole (non-comprehension) for-loop a new scope, because that would make any variables assigned within the loop body local as well. -- Greg Ewing, Computer Science Dept, University of Canterbury, Christchurch, New Zealand http://www.cosc.canterbury.ac.nz/~greg Jul 18 '05 #14

 P: n/a David MacQuigg writes: You can maintain that consistency by extending the list of"boundaries" which define scopes; you already mentioned classes,functions and modules ... now simply add list comprehensions (orloops), and you will maintain perfect consistency of treatment oflocal variables, without leaking variables out of list comprehensions(or loops). I think the current design of Python is the right compromise between narrow scopes that avoid conflicts between identical names and broad scopes that minimize the need for global declarations. Imagine having to declare globals inside every loop that needed to set some value outside of its own tiny little scope. And what if the variable I want to affect is in an enclosing scope, but not the global scope ? Doesn't this rather suggest that the whole global declaration business is rather flawed? It sort of made sense when we only had 3 scopes in Python (only 2 of which were "userland" scopes) , but with nested scopes it's simply not up to the job. Ultimately, the problem can be traced to having no distinction between inctroducting a new binding and rebinding an existing name. Jul 18 '05 #15

 P: n/a "Greg Ewing (using news.cis.dfn.de)" writes: Jacek Generowicz wrote: now simply add list comprehensions (or loops), and you will maintain perfect consistency of treatment of local variables, It wouldn't do to make the whole (non-comprehension) for-loop a new scope, because that would make any variables assigned within the loop body local as well. Sometimes you want that, and sometimes you don't. What you need is a way to distinguish between the two. IOW, you want to distinguish between creating a new binding, and rebinding. In Python both of these are spelt thus: "=", and its actual meaning is determied by the context. With the added spice of the exceptional case of "global". Imagine (for the sake of brevity of argument --- I wouldn't dream of suggesting such a "line-noise" syntax for Python) that you could use "x := 3" to mean "create a new local binding for x", while "x = 3" would mean "find the innermost x and rebind it", with function parameters, loop variables, list comprehension variables all behaving as if they were using ":=". Now you'll find that you gain a lot of flexibility to do what is appropriate with scopes of variables used in loops etc., and you have an opportunity to fix the immutability of closures ... (Of course there are "issues" ... what happens, for example when you say def foo(a): a := 3 a := 4 .... does that make three nested scopes for a?, is it an error?) Jul 18 '05 #16

 P: n/a Jacek Generowicz writes: Imagine (for the sake of brevity of argument --- I wouldn't dream of suggesting such a "line-noise" syntax for Python) that you could use "x := 3" to mean "create a new local binding for x", while "x = 3" would mean "find the innermost x and rebind it", with function parameters, loop variables, list comprehension variables all behaving as if they were using ":=". Now you'll find that you gain a lot of flexibility to do what is appropriate with scopes of variables used in loops etc., and you have an opportunity to fix the immutability of closures ... (Of course there are "issues" ... what happens, for example when you say def foo(a): a := 3 a := 4 ... does that make three nested scopes for a?, is it an error?) Hmm, this is starting to intrigue me. What are the situations that need disambiguating? What situations do (or might) create inner scopes? "def" and "class" are currently the two ways of creating an inner scope (have I overlooked any others?) ... and we are considering the possibility of "for" doing the same (in two different flavours: loops and comprehensions). Current rules can be summarized as: In a scope creating block (def, class), assignment introduces a local binding, unless the name is declared global. It looks like what's missing (because originally there were no other scopes between local and global) is some way of declaring a name to refer to an enclosing scope which may or may not be the global scope. For example: def make(): ... x = 0 ... def show(): print x ... def inc(n): x = x+n ... return show,inc ... show,inc = make() show() 0 inc(3) Traceback (most recent call last): File "", line 1, in ? File "", line 4, in inc UnboundLocalError: local variable 'x' referenced before assignment The problem is that the "x =" inside "def inc():" tells the compiler to treat "x" as local to the scope of "inc", and then the reference to "x" or the RHS of the same line refers to an unbound variable ("x" in the _local_ scope). "global" is there for exactly this sort of situation, except that it originates from a time when there were no nested scopes, so it offers no help if you want to refer to some scope other than the global or local. Imagine we have a "nested" keyword which is similar to "global", only it ensures that the name is found in the nearest enclosing scope. Now the above problem could be resolved by defining "inc" as follows. def make(): x = 0 ... def inc(n): nested x x = x+n ... Works just like global would have done, only it is aware of the other socpes between local and global. "Greg Ewing (using news.cis.dfn.de)" writes: It wouldn't do to make the whole (non-comprehension) for-loop a new scope, because that would make any variables assigned within the loop body local as well. Not if you have a "nested" keyword at your disposal. What situations would this not cover ? Jul 18 '05 #17

 P: n/a On 15 Mar 2004 12:52:14 +0100, Jacek Generowicz wrote: Jacek Generowicz writes: Imagine (for the sake of brevity of argument --- I wouldn't dream of suggesting such a "line-noise" syntax for Python) that you could use "x := 3" to mean "create a new local binding for x", while "x = 3" would mean "find the innermost x and rebind it", with function parameters, loop variables, list comprehension variables all behaving as if they were using ":=". Now you'll find that you gain a lot of flexibility to do what is appropriate with scopes of variables used in loops etc., and you have an opportunity to fix the immutability of closures ... (Of course there are "issues" ... what happens, for example when you say def foo(a): a := 3 a := 4 ... does that make three nested scopes for a?, is it an error?)Hmm, this is starting to intrigue me.What are the situations that need disambiguating?What situations do (or might) create inner scopes?"def" and "class" are currently the two ways of creating an innerscope (have I overlooked any others?) ... and we are considering thepossibility of "for" doing the same (in two different flavours: loopsand comprehensions). Is it (entirely) correct to say that class opens a new scope? I don't think so, since names bound within the class body become attributes of the class object, they are not local variables -- you can reach them from the outside. Current rules can be summarized as: In a scope creating block (def, class), assignment introduces a local binding, unless the name is declared global.It looks like what's missing (because originally there were no otherscopes between local and global) is some way of declaring a name torefer to an enclosing scope which may or may not be the global scope.For example: >>> def make(): ... x = 0 ... def show(): print x ... def inc(n): x = x+n ... return show,inc ... >>> show,inc = make() >>> show() 0 >>> inc(3) Traceback (most recent call last): File "", line 1, in ? File "", line 4, in inc UnboundLocalError: local variable 'x' referenced before assignmentThe problem is that the "x =" inside "def inc():" tells the compilerto treat "x" as local to the scope of "inc", and then the reference to"x" or the RHS of the same line refers to an unbound variable ("x" inthe _local_ scope). "global" is there for exactly this sort ofsituation, except that it originates from a time when there were nonested scopes, so it offers no help if you want to refer to some scopeother than the global or local. There were discussions about this in in the python dev list. The only proposal that stuck in my memory was an extension of the global keyword where you had an option of specifying the scope, something like: def g(*args): x = None def f(*args): global x in g The scope of a name is determined at compile time, so it seems unavoidable that a declaration is needed. But I wished that there were no declarations in Python and some OO form of treating scopes like objects with the local names being its attributes were available -- but I am also well aware that this is a very idiosincratic preference :-) With my best regards, G. Rodrigues Jul 18 '05 #18

 P: n/a Gonçalo Rodrigues writes: Is it (entirely) correct to say that class opens a new scope? I don't think so, class foo: .... a = 3 .... def bar(self): .... print a .... f = foo() f.bar() Traceback (most recent call last): File "", line 1, in ? File "", line 4, in bar NameError: global name 'a' is not defined Bleargh! You are right. Now that you bring it up, I recall bumping up against it before. since names bound within the class body become attributes of the class object, they are not local variables -- you can reach them from the outside. That in itself does not prevent "class" from introducing a scope. It just means that there are ways of getting at things in that scope .... just like here: def foo(): a = [3] def show(): print a[0] def inc(n): a[0] += n return show, inc show, inc = foo() show() # prints 3 inc(2) show() # prints 5 "a" is definitely in the scope introduced by "foo", but you can reach it from the outside. There were discussions about this in in the python dev list. The only proposal that stuck in my memory was an extension of the global keyword where you had an option of specifying the scope, something like: def g(*args): x = None def f(*args): global x in g Hmmm ... the explicit naming of the scope sort of piddles all over the elegance of nested scopes. But maybe the generality of being able to specify *any* enclosing scope has some applications, though none come to mind immediately. OTOH: def g(): x = None def g(): x = None def g(): global x in g Just *which* g are we talking about ? Let's just stick to finding the innermost binding of the name :-) Of course, the name "global" is completely inappropriate, but I guess they're trying to avoid a new keyword. Jul 18 '05 #19

 P: n/a >I think I may have misunderstood your original question. The title ofthe thread is 'loop scope', but your question seems to be specificallyon the loop iteration variable 't'. Just think of it as a normalvariable in the current local scope. I can. But it's not my first inclination. And I would speculate I am far from alone. Having subtleties to be aware of in something as fundamenatal as a for loop is not a great thing, IMO. On the hand hand, it was a long time before any subtleties here had any practical implications to me. I had been getting away with ignorance. But its not a good feeling to know that. t=None #(or something) required prior to a loop would assure I am conscious of what I am getting myself into. Without it, it seems it isn't safe to assume the user understands the full implications of simply complying with required loop syntax. Wouldn't something like this make sense: With a loop iteration variable declared explicitly in the curent scope and prior to the loop, it survives the loop. Otherwise it is treated as a placeholder within the loop, and goes out of scope at its conclusion. All other issues regarding scopes. with loops, are as they are. No new keywords, no overstating the issue. But does 't=None' have any meaning in Python now? I guess if it doesn't anything along the lines of my suggestion doesn't make much sense. Art Jul 18 '05 #20

 P: n/a On Mon, 15 Mar 2004 14:43:20 GMT, Arthur wrote: I think I may have misunderstood your original question. The title ofthe thread is 'loop scope', but your question seems to be specificallyon the loop iteration variable 't'. Just think of it as a normalvariable in the current local scope.I can. But it's not my first inclination. And I would speculate I amfar from alone. Having subtleties to be aware of in something asfundamenatal as a for loop is not a great thing, IMO. On the handhand, it was a long time before any subtleties here had any practicalimplications to me. I had been getting away with ignorance. But itsnot a good feeling to know that.t=None #(or something)required prior to a loop would assure I am conscious of what I amgetting myself into. Without it, it seems it isn't safe to assume theuser understands the full implications of simply complying withrequired loop syntax.Wouldn't something like this make sense:With a loop iteration variable declared explicitly in the curent scopeand prior to the loop, it survives the loop. Otherwise it is treatedas a placeholder within the loop, and goes out of scope at itsconclusion. This is a little too tricky for my taste. Often we need to 'break' from a loop, and subsequently use the value of 't'. If we forget to "declare" 't' outside the loop, then we will have a situation where you get a run-time error if the loop ends without a break. What is the benefit of keeping 't' out of the surrounding local scope?" This whole thread seems pointless unless there is a substantial benefit to changing the current behavior. -- Dave Jul 18 '05 #21

 P: n/a In article , David MacQuigg wrote: On Mon, 15 Mar 2004 14:43:20 GMT, Arthur wrote: t=None #(or something) required prior to a loop would assure I am conscious of what I am getting myself into. Without it, it seems it isn't safe to assume the user understands the full implications of simply complying with required loop syntax. Wouldn't something like this make sense: With a loop iteration variable declared explicitly in the curent scope and prior to the loop, it survives the loop. Otherwise it is treated as a placeholder within the loop, and goes out of scope at its conclusion. This is a little too tricky for my taste. Often we need to 'break' from a loop, and subsequently use the value of 't'. If we forget to "declare" 't' outside the loop, then we will have a situation where you get a run-time error if the loop ends without a break. I didn't read anything there that proposed to make a distinction between `ends with break' and `ends without break.' That would be a bad thing. What is the benefit of keeping 't' out of the surrounding local scope?" This whole thread seems pointless unless there is a substantial benefit to changing the current behavior. Well, the bottom line has to be whether it's easier to read the code and understand what it does. In a procedural language like Python, variable scope is critical to that, so it's important to get it right. Unfortunately, I don't know if there's a good answer. Taking list comprehensions, because that's what the original post took at least as an example and because that's the only case that is new enough to half seriously consider changing - t = f(a/c) ... # and then later, sl = [t * t for t in range(3)] In this case, I would argue that it's an error for t to escape the expression scope _because_ it's used outside that scope - actually I think that was where we came in. My personal view is that a list comprehension should have its own internal scope, period, but is that what `intuition' would lead most Python programmers to expect? I don't know. Donn Cave, do**@u.washington.edu Jul 18 '05 #22

 P: n/a On Mon, 15 Mar 2004 10:38:20 -0700, David MacQuigg wrote: On Mon, 15 Mar 2004 14:43:20 GMT, Arthur wrote:With a loop iteration variable declared explicitly in the curent scopeand prior to the loop, it survives the loop. Otherwise it is treatedas a placeholder within the loop, and goes out of scope at itsconclusion.This is a little too tricky for my taste. Mine too, really. But it was off the cuff, and illustrative. And as I said, the current behavior hasn't caused me any actual problem. There are probably reasons why one can expect ot get away with being blissfully ignorant here. I couldn't/wouldn't do anything with "t", being unaware that it was there. And if I rebind "t" to something else, its the same as if I was orignally binding it. No harm, no foul. Essentailly what happened in the session that brought this up for me was that I goofed, used "t" without binding it to anything (well actually I had without realizing) and got a result that I couldn't make sense of, rather than the error message which I deserved (or would otherwise have deserved). I haven't convinced myself it is possible to write sensible code *and* get caught here, even if unaware of the scoping issue. Though I haven't convinced myself it isn't, either. Often we need to 'break'from a loop, and subsequently use the value of 't'. If we forget to"declare" 't' outside the loop, then we will have a situation whereyou get a run-time error if the loop ends without a break.What is the benefit of keeping 't' out of the surrounding localscope?" This whole thread seems pointless unless there is asubstantial benefit to changing the current behavior.-- Dave Jul 18 '05 #23

 P: n/a t = f(a/c) ... # and then later, sl = [t * t for t in range(3)] In this case, I would argue that it's an error for t to escape the expression scope _because_ it's used outside that scope - actually I think that was where we came in. My personal view is that a list comprehension should have its own internal scope, period, but is that what `intuition' would lead most Python programmers to expect? I don't know. From what I understand, the above case is taken care of in Python 2.4 In the case of: t = f(a/c) .... # and then later, s1 = [] for t in range(3): s1.append(t * t) The behavior is unchanged in 2.4, t gets rebound. - Josiah Jul 18 '05 #24

 P: n/a On Mon, 15 Mar 2004 10:26:41 -0800, Donn Cave wrote:Taking list comprehensions, because that's what the originalpost took at least as an example and because that's the onlycase that is new enough to half seriously consider changing - t = f(a/c) ... # and then later, sl = [t * t for t in range(3)]In this case, I would argue that it's an error for t to escapethe expression scope _because_ it's used outside that scope -actually I think that was where we came in. Yeah, I guess that is where the danger is, if I had been previously bound "t" and had it rebound against my expectations Which was not exactly the case I fell into. Thinking about it, I - and hopefully others - at least have an intuitive sense of knowing what they don't know. I guess there were always enough variable names at my disposal that I have avoided using something as a iterator variable that I have used for some other purpose in the same scope. Just to be safe. And knowing I don't fully understand what is happening under the covers.. Good boy. me. Art My personal viewis that a list comprehension should have its own internal scope,period, but is that what `intuition' would lead most Pythonprogrammers to expect? I don't know. Donn Cave, do**@u.washington.edu Jul 18 '05 #25

 P: n/a In article , Jacek Generowicz wrote:Imagine we have a "nested" keyword which is similar to "global", onlyit ensures that the name is found in the nearest enclosing scope. Nowthe above problem could be resolved by defining "inc" as follows. def make(): x = 0 ... def inc(n): nested x x = x+n ...Works just like global would have done, only it is aware of theother socpes between local and global. "Greg Ewing (using news.cis.dfn.de)" writes: > It wouldn't do to make the whole (non-comprehension) > for-loop a new scope, because that would make any > variables assigned within the loop body local as well.Not if you have a "nested" keyword at your disposal.What situations would this not cover ? Far too few. After the `nested x` statement comes `nested nested x` and `nested nested nested x`, with the accumulating maintenance headaches. All so that programmers can choose data names badly. Almost like running into `continue 17` within a nest of loops. Regards. Mel. Jul 18 '05 #26

 P: n/a mw*****@the-wire.com (Mel Wilson) writes: Far too few. After the `nested x` statement comes `nested nested x` and `nested nested nested x`, Nope. You would never write more than one "nested". It would be an instruction to Python _not_ to treat the name as local, just because there is an assignment to the name in the local scope. The nearest scope that has a binding for the name shadows all others ... just like nested scopes work today. The only problem (today) is that an assignment to the name creates a binding in the local scope, so there is no way of _re_-binding a name in an enclosing scope. Languages which support nested scopes have been around for decades, and none of them have (to my knowledge) found the need for specifying which nested scope you want to look in; the nearest one is the one you want. That's, partly, the point of nested scopes. Jul 18 '05 #27

 P: n/a In article , Jacek Generowicz wrote:mw*****@the-wire.com (Mel Wilson) writes: Far too few. After the `nested x` statement comes `nested nested x` and `nested nested nested x`,Nope. You would never write more than one "nested". It would be aninstruction to Python _not_ to treat the name as local, [ ... ] Sorry. Bad reading. I came to my senses sometime yesterday. I don't like the idea of rebinding names non-locally, but that's taste. Nothing to do with the logic of your idea. Regards. Mel. Jul 18 '05 #28

 P: n/a Jacek Generowicz wrote in message news:... [snip] Imagine (for the sake of brevity of argument --- I wouldn't dream of suggesting such a "line-noise" syntax for Python) that you could use "x := 3" to mean "create a new local binding for x", while "x = 3" would mean "find the innermost x and rebind it", with function parameters, loop variables, list comprehension variables all behaving as if they were using ":=". Now you'll find that you gain a lot of flexibility to do what is appropriate with scopes of variables used in loops etc., and you have an opportunity to fix the immutability of closures ... (Of course there are "issues" ... what happens, for example when you say def foo(a): a := 3 a := 4 ... does that make three nested scopes for a?, is it an error?) One way to avoid this problem is to have an explicit scope-creating construct instead. def foo(a): scope outer: a = 3 scope inner: a = 4 print a # prints 4 print outer.a # prints 3 print foo.a # prints the function parameter print a # inner.a is out of scope, so prints 3 foo.b = 5 # Creates a new function-scope variable. print b # prints 5 Jul 18 '05 #29

 P: n/a > One way to avoid this problem is to have an explicit scope-creating construct instead. def foo(a): scope outer: a = 3 scope inner: a = 4 print a # prints 4 print outer.a # prints 3 print foo.a # prints the function parameter print a # inner.a is out of scope, so prints 3 foo.b = 5 # Creates a new function-scope variable. print b # prints 5 Ick. Thank god Python doesn't seem to be heading in this direction. - Josiah Jul 18 '05 #30

 P: n/a mw*****@the-wire.com (Mel Wilson) writes: I don't like the idea of rebinding names non-locally. Though most languages with nested scopes do exactly that (as far as I am aware). Jul 18 '05 #31

 P: n/a da*****@yahoo.com (Dan Bishop) writes: One way to avoid this problem is to have an explicit scope-creating construct instead. def foo(a): scope outer: a = 3 scope inner: a = 4 print a # prints 4 print outer.a # prints 3 print foo.a # prints the function parameter print a # inner.a is out of scope, so prints 3 foo.b = 5 # Creates a new function-scope variable. print b # prints 5 I think that the elegance of nested scopes relies on the language being able to find the innermost scope which contains the given name, _without_ help from the programmer. But this relies on being able to distinguish binding from re-binding. Jul 18 '05 #32

 P: n/a Josiah Carlson wrote in message news:... One way to avoid this problem is to have an explicit scope-creating construct instead. def foo(a): scope outer: a = 3 scope inner: a = 4 print a # prints 4 print outer.a # prints 3 print foo.a # prints the function parameter print a # inner.a is out of scope, so prints 3 foo.b = 5 # Creates a new function-scope variable. print b # prints 5 Ick. Thank god Python doesn't seem to be heading in this direction. I agree. Just because this was my idea doesn't mean I have to like it ;-) I'm satified with the scope rules the way they are, except for list comprehensions. Jul 18 '05 #33

 P: n/a On 19 Mar 2004 12:52:08 -0800, da*****@yahoo.com (Dan Bishop) wrote: Josiah Carlson wrote in message news:... > One way to avoid this problem is to have an explicit scope-creating > construct instead. > > def foo(a): > scope outer: > a = 3 > scope inner: > a = 4 > print a # prints 4 > print outer.a # prints 3 > print foo.a # prints the function parameter > print a # inner.a is out of scope, so prints 3 > foo.b = 5 # Creates a new function-scope variable. > print b # prints 5 Ick. Thank god Python doesn't seem to be heading in this direction.I agree. Just because this was my idea doesn't mean I have to like it ;-)I'm satified with the scope rules the way they are, except for list comprehensions. There is one small change I would make. Nested scopes should apply to *any* nested code, including nested classes. This would make the rules much simpler and easy to teach. -- Dave Jul 18 '05 #34

### This discussion thread is closed

Replies have been disabled for this discussion.