Nested Scopes unintended behaviour ?

Emile van Sebille emile at fenx.com
Wed Mar 17 11:44:03 EDT 2010


On 3/17/2010 8:16 AM Michael Sparks said...
> Hi,
>
>
> Is the following behaviour expected ?

In short, yes.  Assignment within a function forces the variable to 
locals.  You can get around it like:

>
> Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15)
> [GCC 4.4.1] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> def Toggler(F, B):
> ...     print F("Hello")
> ...     print F("Hello")
> ...     print F("Hello")
> ...     print F("Hello")
> ...     print F("Hello")
> ...
>>>> def Switcher(A,B):
> ...     on=True
> ...     def swtchfun(msg):

--->      def swtchfun(msg, on=on):

> ...         on_ = on
> ...         if on:
> ...             on = False
> ...             print "Switched to A"
> ...             return A
> ...         else:
> ...             print "Switched to B"
> ...             return B
> ...     #
> ...     return Toggler(swtchfun,True)
> ...
>>>> Switcher(1,2)
> Traceback (most recent call last):
>    File "<stdin>", line 1, in<module>
>    File "<stdin>", line 13, in Switcher
>    File "<stdin>", line 2, in Toggler
>    File "<stdin>", line 4, in swtchfun
> UnboundLocalError: local variable 'on' referenced before assignment
>
> The reason I ask is because logically it makes sense. The on_ = on
> statement should resolve "on" to be the value on in the enclosing
> scope, however it appears that the "on = False" statement is taking
> priority. The reason I say this is because if you remove the "on =
> False" line you get the expected name resolution:
>
>>>> def Toggler(F, B):
> ...     print F("Hello")
> ...     print F("Hello")
> ...     print F("Hello")
> ...     print F("Hello")
> ...     print F("Hello")
> ...
>>>> def Switcher(A,B):
> ...     on=True
> ...     def swtchfun(msg):
> ...         on_ = on
> ...         if on:
> ...             print "Switched to A"
> ...             return A
> ...         else:
> ...             print "Switched to B"
> ...             return B
> ...     #
> ...     return Toggler(swtchfun,True)
> ...
>>>> Switcher(1,2)
> Switched to A
> 1
>
> ie it looks like python is not looking at the expected scope in the
> first instance.
>
> To me it looks like a bug, but I can also see a rationale where it's
> considered a feature (because the "on" is on the left hand side
> resolving the value to a local, rather than a value in an enclosed
> scope)
>
> I know that you can work around this as follows:
> Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15)
> [GCC 4.4.1] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> def Toggler(F, B):
> ...     print F("Hello")
> ...     print F("Hello")
> ...     print F("Hello")
> ...     print F("Hello")
> ...
>>>> def Switcher(A,B):
> ...     def switchgen():
> ...         while True:
> ...             yield A
> ...             yield B
> ...     G = switchgen()
> ...     def swtchfun(msg):
> ...         return G.next()
> ...     #
> ...     return Toggler(swtchfun,True)
> ...
>>>>
>>>> Switcher(1,2)
> 1
> 2
> 1
> 2
>
> But I'm curious as to whether the nested scope issue above is
> considered a bug or a feature, so I can deal with it appropriately.
>
> Any comments welcome :-)
>
> Regards,
>
>
> Michael.
> --
> http://yeoldeclue.com/blog
> http://www.kamaelia.org/Home.html
> http://twitter.com/kamaelian
>
>
>





More information about the Python-list mailing list