block scope?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Alex Martelli

    #16
    Re: block scope?

    Aahz <aahz@pythoncra ft.comwrote:
    In article <1hw7kzo.1hepj3 c1who5zhN%aleax @mac.com>,
    Alex Martelli <aleax@mac.comw rote:
    Steve Holden <steve@holdenwe b.comwrote:
    >
    What do you think the chances are of this being accepted for Python 3.0?
    It is indeed about the most rational approach, though of course it does
    cause problems with dynamic namespaces.
    What problems do you have in mind? The compiler already determines the
    set of names that are local variables for a function; all it needs to do
    is diagnose an error or warning if the set of names for a nested
    function overlaps with that of an outer one.
    >
    exec?
    option 1: that just runs the compiler a bit later -- thus transforming
    ClashingVariabl eError into a runtime issue, exactly like it already does
    for SyntaxError.

    option 2: since a function containing any exec statement does not
    benefit from the normal optimization of local variables, let it also
    forgo the normal diagnosis of shadowed/clashing names.

    option 3: extend the already-existing prohibition of mixing exec with
    nested functions:
    >>def outer():
    .... def inner(): return x
    .... exec('x=23')
    .... return inner()
    ....
    File "<stdin>", line 3
    SyntaxError: unqualified exec is not allowed in function 'outer' it
    contains a nested function with free variables

    to prohibit any mixing of exec and nested functions (not just those
    cases where the nested function has free variables).


    My personal favorite is option 3.


    Alex

    Comment

    • Paul Rubin

      #17
      Re: block scope?

      aleax@mac.com (Alex Martelli) writes:
      exec?
      option 1: that just runs the compiler a bit later ...
      Besides exec, there's also locals(), i.e.
      locals['x'] = 5
      can shadow a variable. Any bad results are probably deserved ;)

      Comment

      • MRAB

        #18
        Re: block scope?

        On Apr 7, 8:50 am, James Stroud <jstr...@mbi.uc la.eduwrote:
        Paul Rubin wrote:
        John Nagle <n...@animats.c omwrites:
        In a language with few declarations, it's probably best not to
        have too many different nested scopes. Python has a reasonable
        compromise in this area. Functions and classes have a scope, but
        "if" and "for" do not. That works adequately.
        >
        I think Perl did this pretty good. If you say "my $i" that declares
        $i to have block scope, and it's considered good practice to do this,
        but it's not required. You can say "for (my $i=0; $i < 5; $i++) { ... }"
        and that gives $i the same scope as the for loop. Come to think of it
        you can do something similar in C++.
        >
        How then might one define a block? All lines at the same indent level
        and the lines nested within those lines?
        >
        i = 5
        for my i in xrange(4):
        if i: # skips first when i is 0
        my i = 100
        if i:
        print i # of course 100
        break
        print i # i is between 0 & 3 here
        print i # i is 5 here
        >
        Doesn't leave a particularly bad taste in one's mouth, I guess (except
        for the intended abuse).
        >
        How about something like this instead:

        i = 5
        block:
        for i in xrange(4):
        if i: # skips first when i is 0
        block:
        i = 100
        if i:
        print i # of course 100
        break
        print i # i is between 0 & 3 here
        print i # i is 5 here

        Any variable that's assigned to within a block would be local to that
        block, as it is in functions.

        Comment

        • Alex Martelli

          #19
          Re: block scope?

          Paul Rubin <http://phr.cx@NOSPAM.i nvalidwrote:
          aleax@mac.com (Alex Martelli) writes:
          exec?
          option 1: that just runs the compiler a bit later ...
          >
          Besides exec, there's also locals(), i.e.
          locals['x'] = 5
          can shadow a variable. Any bad results are probably deserved ;)
          >>locals['x']=5
          Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          TypeError: 'builtin_functi on_or_method' object does not support item
          assignment

          I suspect you want to index the results of calling locals(), rather than
          the builtin function itself. However:
          >>def f():
          .... locals()['x'] = 5
          .... return x
          ....
          >>f()
          Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          File "<stdin>", line 3, in f
          NameError: global name 'x' is not defined

          No "shadowing" , as you see: the compiler knows that x is NOT local,
          because it's not assigned to (the indexing of locals() does not count:
          the compiler's not expected to detect that), so it's going to look it up
          as a global variable (and not find it in this case).

          I think that ideally there should be a runtime error when assigning an
          item of locals() with a key that's not a local variable name (possibly
          excepting functions containing exec, which are kind of screwy anyway).


          Alex

          Comment

          • Paul Rubin

            #20
            Re: block scope?

            aleax@mac.com (Alex Martelli) writes:
            >locals['x']=5
            Traceback (most recent call last):
            File "<stdin>", line 1, in <module>
            TypeError: 'builtin_functi on_or_method' object does not support item
            assignment

            Whoops, yeah, meant "locals()['x'] = 5".
            I think that ideally there should be a runtime error when assigning an
            item of locals() with a key that's not a local variable name (possibly
            excepting functions containing exec, which are kind of screwy anyway).
            I have no opinion of this, locals() has always seemed like a crazy
            part of the language to me and I never use it. I'd be happy to see it
            gone since it makes compiling a lot easier.

            Comment

            • John Nagle

              #21
              Re: block scope?

              Paul Rubin wrote:
              aleax@mac.com (Alex Martelli) writes:
              I have no opinion of this, locals() has always seemed like a crazy
              part of the language to me and I never use it. I'd be happy to see it
              gone since it makes compiling a lot easier.
              I think of that, from a compiler perspective, as one of the features
              that, if used, means you have to switch to a more inefficient representation.

              I encourage the hard-code optimizing compiler people to keep plugging
              away on Python. It's a convenient way to program, but the implementations
              are slower than they should be a decade into the language's life cycle.

              John Nagle

              Comment

              • Alexander Schmolck

                #22
                Re: block scope?

                Neal Becker <ndbecker2@gmai l.comwrites:
                One thing I sometimes miss, which is common in some other languages (c++),
                is idea of block scope. It would be useful to have variables that did not
                outlive their block, primarily to avoid name clashes. This also leads to
                more readable code.
                I have on occassion used lambda as a poor-man's let, but only if I needed to
                avoid multiple evaluation:

                res = (lambda x=blah(...), y=blahz(...): f(x*y,x+y))()

                I'm sure most people would debate it's more readable, but it's IMO superior to
                cleaning up manually with ``del``. I sometimes also find it useful to avoid
                cluttering up the interactive shell.

                'as

                Comment

                • Paddy

                  #23
                  Re: block scope?

                  On Apr 7, 4:48 am, James Stroud <jstr...@mbi.uc la.eduwrote:
                  Neal Becker wrote:
                  One thing I sometimes miss, which is common in some other languages (c++),
                  is idea of block scope. It would be useful to have variables that did not
                  outlive their block, primarily to avoid name clashes. This also leads to
                  more readable code. I wonder if this has been discussed?
                  >
                  Probably, with good code, block scope would be overkill, except that I
                  would welcome list comprehensions to have a new scope:
                  >
                  pyi
                  ------------------------------------------------------------
                  Traceback (most recent call last):
                  File "<ipython console>", line 1, in <module>
                  <type 'exceptions.Nam eError'>: name 'i' is not defined
                  >
                  py[i for i in xrange(4)]
                  [0, 1, 2, 3]
                  pyi # hoping for NameError
                  3
                  Yep, i think that we need consistent scope rules for
                  listexps and genexps. Isn't it coming in 3.0?

                  If it is, then maybe it will be back-ported to
                  Python 2.6.

                  In Python 2.5 we have the following:
                  >>[k for k in (j for j in range(5))]
                  [0, 1, 2, 3, 4]
                  >>k
                  4
                  >>j
                  Traceback (most recent call last):
                  File "<interacti ve input>", line 1, in <module>
                  NameError: name 'j' is not defined
                  >>>
                  - Paddy.

                  Comment

                  • Georg Brandl

                    #24
                    Re: block scope?

                    Alex Martelli schrieb:
                    Paul Rubin <http://phr.cx@NOSPAM.i nvalidwrote:
                    >
                    >aleax@mac.com (Alex Martelli) writes:
                    exec?
                    option 1: that just runs the compiler a bit later ...
                    >>
                    >Besides exec, there's also locals(), i.e.
                    > locals['x'] = 5
                    >can shadow a variable. Any bad results are probably deserved ;)
                    >
                    >>>locals['x']=5
                    Traceback (most recent call last):
                    File "<stdin>", line 1, in <module>
                    TypeError: 'builtin_functi on_or_method' object does not support item
                    assignment
                    >
                    I suspect you want to index the results of calling locals(), rather than
                    the builtin function itself. However:
                    >
                    >>>def f():
                    ... locals()['x'] = 5
                    ... return x
                    ...
                    >>>f()
                    Traceback (most recent call last):
                    File "<stdin>", line 1, in <module>
                    File "<stdin>", line 3, in f
                    NameError: global name 'x' is not defined
                    >
                    No "shadowing" , as you see: the compiler knows that x is NOT local,
                    because it's not assigned to (the indexing of locals() does not count:
                    the compiler's not expected to detect that), so it's going to look it up
                    as a global variable (and not find it in this case).
                    Even assignments to real local variable names in the locals() result do
                    normally not result in the variable having a new value.
                    I think that ideally there should be a runtime error when assigning an
                    item of locals() with a key that's not a local variable name (possibly
                    excepting functions containing exec, which are kind of screwy anyway).
                    I would make the locals() result completely independent from the frame,
                    and document that it is read only.

                    (though, this needs some other way for trace functions to interact with
                    the frame's local variables.)

                    Georg

                    Comment

                    • Bruno Desthuilliers

                      #25
                      Re: block scope?

                      Paul Rubin a écrit :
                      aleax@mac.com (Alex Martelli) writes:
                      >
                      >>>>>locals['x']=5
                      >>
                      >>Traceback (most recent call last):
                      > File "<stdin>", line 1, in <module>
                      >>TypeError: 'builtin_functi on_or_method' object does not support item
                      >>assignment
                      >
                      >
                      >
                      Whoops, yeah, meant "locals()['x'] = 5".
                      >
                      >
                      >>I think that ideally there should be a runtime error when assigning an
                      >>item of locals() with a key that's not a local variable name (possibly
                      >>excepting functions containing exec, which are kind of screwy anyway).
                      >
                      >
                      I have no opinion of this, locals() has always seemed like a crazy
                      part of the language to me and I never use it. I'd be happy to see it
                      gone since it makes compiling a lot easier.
                      I personally find locals() handy in few cases, like

                      def output():
                      foo = 42
                      bar = baaz()
                      quux = blah(foo, bar)
                      return "the %(bar)s is %(foo)d and the %(quux)s shines" % locals()

                      or:

                      class Foo(object):
                      @apply
                      def bar():
                      def fget(self):
                      return self._quux / 42
                      def fset(self, value):
                      self._quux = value * 42
                      return property(**loca ls())


                      I'd be very unhappy to see it gone...

                      Comment

                      Working...