Nested scopes, and augmented assignment

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Antoon Pardon

    #31
    Re: Nested scopes, and augmented assignment

    On 2006-07-07, Terry Reedy <tjreedy@udel.e duwrote:
    >
    "Antoon Pardon" <apardon@forel. vub.ac.bewrote in message
    news:slrneapmfr .at1.apardon@rc pc42.vub.ac.be. ..
    >And if Nested variables are harmfull,
    >
    I don't know if anyone said that they were, but Guido obviously does not
    think so, or he would not have added them. So skip that.
    >
    >what is then the big difference between rebinding them and mutating them
    >
    A variable is a name. Name can be rebound (or maybe not) but they cannot
    be mutated. Only objects (with mutation methods) can be mutated. In other
    words, binding is a namespace action and mutation is an objectspace action.
    In Python, at least, the difference is fundamental.
    >
    Or, in other other words, do not be fooled by the convenient but incorrect
    abbreviated phrase 'mutate a nested variable'.
    I'm not fooled by that phrase. I just think the mutate vs rebind
    explanation is not complete.

    If we have two statements "a = b" and "c.d = b" the fact that a is being
    rebound while c is mutated doesn't explain why we allow c to be searched
    out of the local scope.

    By only stating that the first statement is a rebinding and the second
    is a mutation and that this is a fundamental difference in python you
    seem to suggest that this fundamental differenence implies this
    difference in searching scopes. Python could have made the choice
    that in an assignment the variable on the left side was always to
    be searched in local space so that code like the following would
    throw: UnboundLocalErr or: local variable 'c' referenced before assignment

    c = SomeObject
    def f():
    c.a = 5

    Now I'm not arguing python should have made this choice. But the
    possibility shows IMO this has more to do with search policies
    of names than with the distinction between a rebinding and a mutation.

    AFAIK when nested scopes where introduced everyone agreed that scopes
    had to have access to outer scopes. There were voices that supported
    allowing a rebinding in an outer scope but no consensus on how to
    do this was reached, so this possibility was dropped. So we can't
    rebind an outer scope variable but we can mutate such a variable
    because for mutation we only need access.
    >I understand that python evolved and that this sometimes results
    >in things that in hindsight could have been done better.
    >
    So does Guido. That is one explicit reason he gave for not choosing any of
    the nunerous proposals for the syntax and semantics of nested scope write
    access. In the face of anti-consensus among the developers and no
    particular personal preference, he decided, "Better to wait than roll the
    dice and make the wrong, hard to reverse, choice now". (Paraphrased quote)
    >
    >>I have to wonder if someone really thought this through at design time
    >
    Giving the actual history of, if anything, too many people thinking too
    many different thoughts, this is almost funny.
    Maybe I didn't made myself clear enough, but I never meant to imply
    people hadn't thought thouroughly about this. If I gave you this
    impression I appologize. What I was wondering about was that those
    that had thought about it, would have reached a certain conclusion
    that seemed suggested.
    Recently however, Guido has rejected most proposals to focus attention on
    just a few variations and possibly gain a consensus. So I think there is
    at least half a chance that some sort of nested scope write access will
    appear in 2.6 or 3.0.
    Well I have browsed the discussion, which is why I react so lately to
    this, and there is one thing I wonder about. As far as I can see no
    suggestion removes the difference in the default search. The following
    code will still work and won't need an outer statement. (or global,
    nonlocal or whatever it will be)

    c = SomeObject
    def f():
    c.a = 5

    I don say they have to change this, but since it seemed decided this
    was a python3k thing, i think the question deserved to be raised.

    But I'm glad with this turn of events anyhow.

    Just my 2 cent.

    --
    Antoon Pardon

    Comment

    • Antoon Pardon

      #32
      Re: Nested scopes, and augmented assignment

      On 2006-07-07, Piet van Oostrum <piet@cs.uu.nlw rote:
      >>>>>Antoon Pardon <apardon@forel. vub.ac.be(AP) wrote:
      >
      >>APOn 2006-07-07, Piet van Oostrum <piet@cs.uu.nlw rote:
      >>>>>>>>Antoo n Pardon <apardon@forel. vub.ac.be(AP) wrote:
      >>>>
      >>APCould you maybe clarify what problem we are discussing? All I wrote
      >>APwas that with an assignment the search for the lefthand variable
      >>APdepends on whether the lefthand side is a simple variable or
      >>APmore complicated.
      >>>>
      >>>What do you mean with `the lefthand variable'? Especially when talking
      >>>about `complicated lefthand sides'?
      >
      >>APThe name on the left side of an assignment that refers to a variable,
      >>APas opposed to names that are attributes.
      >
      So let me get it clear:
      In a.b = c, a is the lefthand variable, but b is not?
      Yes, b is an attribute of a
      If that is what you mean then I interpret your statement
      >>AP`with an assignment the search for the lefthand variable
      >>APdepends on whether the lefthand side is a simple variable or
      >>APmore complicated'
      >
      as meaning that the search for `a' in `a.b = c' would be different than the
      search for `a' in `a = b'.
      It is conceptually different. In the line 'a = b' you don't need to
      search for the scope of a. You know it is the current scope, if you
      want to know the scope of b on the other hand, you need to search
      for statement where it is assigned to.

      Sure you can set things up in the interpreter so that the same search
      routine is used, but that is IMO an implementation detail.
      Well, it is not. But I can understand the
      confusion. Namely, `a = b' introduces a binding for `a' in the local scope,
      unless `a' was declared global. So the search will find `a' in the local
      scope and it stops there. On the other hand `a.b = c' will not introduce a
      binding for `a'. So the search for `a' may stop in the local space (if
      there was another binding for `a' in the local scope) or it may need to
      continue to outer scopes. The difference, however is not the
      complicatedness of the lefthand side but whether the local scope contains a
      binding for the variable.
      The complicatedness of the lefthand side, decided on whether the
      variable was introduced in the local scope or not during startup
      time. So that complicatedness decided whether the search was
      to stop at the local level or not.

      --
      Antoon Pardon

      Comment

      • Piet van Oostrum

        #33
        Re: Nested scopes, and augmented assignment

        >>>>Antoon Pardon <apardon@forel. vub.ac.be(AP) wrote:
        >APIt is conceptually different. In the line 'a = b' you don't need to
        >APsearch for the scope of a. You know it is the current scope, if you
        Except when it has been declared global.
        >APwant to know the scope of b on the other hand, you need to search
        >APfor statement where it is assigned to.
        >APSure you can set things up in the interpreter so that the same search
        >AProutine is used, but that is IMO an implementation detail.
        >>Well, it is not. But I can understand the
        >>confusion. Namely, `a = b' introduces a binding for `a' in the local scope,
        >>unless `a' was declared global. So the search will find `a' in the local
        >>scope and it stops there. On the other hand `a.b = c' will not introduce a
        >>binding for `a'. So the search for `a' may stop in the local space (if
        >>there was another binding for `a' in the local scope) or it may need to
        >>continue to outer scopes. The difference, however is not the
        >>complicatedne ss of the lefthand side but whether the local scope contains a
        >>binding for the variable.
        >APThe complicatedness of the lefthand side, decided on whether the
        >APvariable was introduced in the local scope or not during startup
        >APtime. So that complicatedness decided whether the search was
        >APto stop at the local level or not.
        No, it doesn't. There could be another binding in the same scope. The
        complicatedness of this particular assignment doesn't decide anything about
        how to search for 'a', but rather the presence or absence of a binding
        anywhere in the scope.
        --
        Piet van Oostrum <piet@cs.uu.n l>
        URL: http://www.cs.uu.nl/~piet [PGP 8DAE142BE17999C 4]
        Private email: piet@vanoostrum .org

        Comment

        • Antoon Pardon

          #34
          Re: Nested scopes, and augmented assignment

          On 2006-07-09, Piet van Oostrum <piet@cs.uu.nlw rote:
          >>>>>Antoon Pardon <apardon@forel. vub.ac.be(AP) wrote:
          >
          >>APIt is conceptually different. In the line 'a = b' you don't need to
          >>APsearch for the scope of a. You know it is the current scope, if you
          >
          Except when it has been declared global.
          Yes, I ignored that possibilitym because as far as I understood we
          were discussing variables in intermediate scopes.
          >>APwant to know the scope of b on the other hand, you need to search
          >>APfor statement where it is assigned to.
          >
          >>APSure you can set things up in the interpreter so that the same search
          >>AProutine is used, but that is IMO an implementation detail.
          >
          >>>Well, it is not. But I can understand the
          >>>confusion. Namely, `a = b' introduces a binding for `a' in the local scope,
          >>>unless `a' was declared global. So the search will find `a' in the local
          >>>scope and it stops there. On the other hand `a.b = c' will not introduce a
          >>>binding for `a'. So the search for `a' may stop in the local space (if
          >>>there was another binding for `a' in the local scope) or it may need to
          >>>continue to outer scopes. The difference, however is not the
          >>>complicatedn ess of the lefthand side but whether the local scope contains a
          >>>binding for the variable.
          >
          >>APThe complicatedness of the lefthand side, decided on whether the
          >>APvariable was introduced in the local scope or not during startup
          >>APtime. So that complicatedness decided whether the search was
          >>APto stop at the local level or not.
          No, it doesn't. There could be another binding in the same scope.
          Indeed there could be. But I hoped you would understand I was just
          keeping things simple, with a simple example.
          The
          complicatedness of this particular assignment doesn't decide anything about
          how to search for 'a', but rather the presence or absence of a binding
          anywhere in the scope.
          I'll word it differently. If the compiler encounters a line like 'a = b'
          then you know from that line alone that the search space for a will be
          limited to the local scope. If you encounter a line like 'a.c = b' then
          you have no such knowledge. A line like 'a = b' will cause the compilor
          that at call time variable a will be added to the local scope, a line like
          'a.c = b' will not have that effect. So a line like 'a = b' has an
          influence on what the search space is for variable a, while a line
          like 'a.c = b' doesn't. So the complicatedness on the leftside decides
          whether or not the compilor will take certain actions with regards to
          the search space of the variable on the left side.

          And yes I'm again ignoring global.

          --
          Antoon Pardon

          Comment

          • Antoon Pardon

            #35
            Re: Nested scopes, and augmented assignment

            On 2006-07-08, Dennis Lee Bieber <wlfraed@ix.net com.comwrote:
            On 8 Jul 2006 18:52:56 GMT, Antoon Pardon <apardon@forel. vub.ac.be>
            declaimed the following in comp.lang.pytho n:
            >
            >
            >>
            >I'm not fooled by that phrase. I just think the mutate vs rebind
            >explanation is not complete.
            >>
            >If we have two statements "a = b" and "c.d = b" the fact that a is being
            >rebound while c is mutated doesn't explain why we allow c to be searched
            >out of the local scope.
            >>
            The "search" is not different, per se... It is only after the object
            is found that the difference becomes apparent -- a rebinding changes an
            object's ID, and is not permitted for a non-local UNLESS a "global"
            statement appears before any usage of the name.
            >
            "c.d =..." has absolutely no effect on the ID of object C; in that
            aspect it is a read-only look-up of "c". IOWs, the same look-up as would
            be used if "c" were on the RHS of the statement.
            >
            >be searched in local space so that code like the following would
            >throw: UnboundLocalErr or: local variable 'c' referenced before assignment
            >>
            >c = SomeObject
            >def f():
            > c.a = 5
            >>
            What would you say the behavior should be for:
            >
            c.a = c.b
            vs
            la = c.b
            >
            The look-up of "c" is the same on both sides of the statement; local
            (not found) then global (found), THEN the operation is applied. On both
            sides "c" is a read-only look-up (that is, no changes to the ID of "c"
            -- no rebinding -- take place).
            >
            Are you suggesting we need to use "global c" in order to have "c.b"
            on the RHS? By that logic, we would also need "global sys" to reference
            "sys.argv" inside a function definition. Remember -- the modules loaded
            by "import" are just more "SomeObject " samples...
            I think you are misunderstandin g what I was getting at. This example was
            not meant to illustrate how I think python should behave. I thought I
            had made that clear.

            When someone gets confused over the difference between rebinding or mutating
            a variable on an intermediate scope, the explanation he mostly seems to get
            boils down to: one is rebinding, the other is mutation, this is a fundametal
            difference in python.

            My impression is that they seem to say that the fundamental difference
            between mutation and rebinding implies the specific behaviour python
            has now. IMO this explanation is incomplete. The python developers
            could have chosen that a line like 'c.a = ...' would have resulted
            in c being included in the local scope. Then rebinding and mutation
            would still be fundamentally different from each other but the specific
            confusion over why 'k[0] = ...' worked as expeced but 'k = ...' didn't,
            will disappear.

            So I only used this example as an illustration why I think the usual
            explanation is not completed. This example is not to be taken as an
            illustration of how I think python should behave.

            --
            Antoon Pardon

            Comment

            • Piet van Oostrum

              #36
              Re: Nested scopes, and augmented assignment

              >>>>Antoon Pardon <apardon@forel. vub.ac.be(AP) wrote:
              >APWhen someone gets confused over the difference between rebinding or
              >APmutating a variable on an intermediate scope, the explanation he
              >APmostly seems to get boils down to: one is rebinding, the other is
              >APmutation, this is a fundametal difference in python.
              >APMy impression is that they seem to say that the fundamental difference
              >APbetween mutation and rebinding implies the specific behaviour python
              >APhas now. IMO this explanation is incomplete. The python developers
              >APcould have chosen that a line like 'c.a = ...' would have resulted
              >APin c being included in the local scope. Then rebinding and mutation
              >APwould still be fundamentally different from each other but the specific
              >APconfusion over why 'k[0] = ...' worked as expeced but 'k = ...' didn't,
              >APwill disappear.
              That seems nonsense to me. If they had chosen that 'c.a = ...' would imply
              that c would become a local variable, what would the value of c have to be
              then, if there was no prior direct assignment to c? Would it become a new
              binding like in 'c = ...'? From what class should it become an instance? Or
              would it become a copy of the value that 'c' has in an outer scope? I don't
              know any programming language where an assignment to c.a does create a new
              c, rather than modifying the existing value of c. That would have been a
              very strange language design. Similarly for 'k[0] = ...'. What would happen
              with the other elements of k?

              There are no situations in Python where an assignment to c.a or c[0]
              suddenly lets spring c into existence. You always need an already existing
              binding for c for this to be valid. And it always uses that binding, and
              doesn't move or copy it to a different block.

              Some of the confusing originates from the fact that assignment in Python is
              subtly different from assignment in other programming languages. In most
              languages variables denote memory locations or collections of memory
              locations. An assignment then means changing the contents of those memory
              locations. In python variables are bound to values, and assignment means
              (re)binding the name to a possibly different value. With an example: most
              other languages have boxes with the name of the variable on them. An
              assignment changes the contents of the box. In Python you have values
              (objects) and an assignment means sticking a label with the name of the
              variable on the object. Often the difference is unnoticable, but there are
              subtle cases where this really makes a difference.

              When the lefthandside of an assignment is an object attribute, subscription
              or slice then the assignment is syntactic sugar for a mutation operation
              implemented by the object, which usually changes the value of the object
              but could do something completely different.

              (Finally, the lefthandside can also be a [nested] tuple or list, in which
              case it is a collection of parallel assignments. And oh yes, there are also
              other binding operations e.g. a function or class definition.)
              --
              Piet van Oostrum <piet@cs.uu.n l>
              URL: http://www.cs.uu.nl/~piet [PGP 8DAE142BE17999C 4]
              Private email: piet@vanoostrum .org

              Comment

              • Antoon Pardon

                #37
                Re: Nested scopes, and augmented assignment

                This is probably my last response to you in this thread. My impression
                is that for the moment nothing productive can come from this exchange.
                I have the feeling that you are not reading so much with the interntion
                of understanding what I want to say, but with the intention of
                confirming your suspition that I just don't have a clue.

                It seems this is turing into some competition where I have
                somehow to defend my understanding of python an you trying to
                show how little I really understand. Since I don't feel the
                need to prove myself here, I will simply bow out.

                On 2006-07-09, Piet van Oostrum <piet@cs.uu.nlw rote:
                >>>>>Antoon Pardon <apardon@forel. vub.ac.be(AP) wrote:
                >
                >>APWhen someone gets confused over the difference between rebinding or
                >>APmutating a variable on an intermediate scope, the explanation he
                >>APmostly seems to get boils down to: one is rebinding, the other is
                >>APmutation, this is a fundametal difference in python.
                >
                >>APMy impression is that they seem to say that the fundamental difference
                >>APbetween mutation and rebinding implies the specific behaviour python
                >>APhas now. IMO this explanation is incomplete. The python developers
                >>APcould have chosen that a line like 'c.a = ...' would have resulted
                >>APin c being included in the local scope. Then rebinding and mutation
                >>APwould still be fundamentally different from each other but the specific
                >>APconfusion over why 'k[0] = ...' worked as expeced but 'k = ...' didn't,
                >>APwill disappear.
                >
                That seems nonsense to me. If they had chosen that 'c.a = ...' would imply
                that c would become a local variable, what would the value of c have to be
                then, if there was no prior direct assignment to c?
                I'm sorry to see you missed it, but since I had answered this already in
                this thread I saw at the moment no need to repeat it: There would be no
                value for c, the line would raise an UnboundLocalErr or.

                I also don't understand why you take the trouble of attacking this
                possibility. It's wasn't presented as a suggestion for changing python.
                It was used as an illustration of why I think some explanation needs
                to be worked out more. So even if this turns out to be the worst
                possible that could ever happen to python, unless you think people
                needing the original explanation will grasp the implication of this
                possibility immediately, the point I wanted to illustrate seems to
                stand.

                --
                Antoon Pardon

                Comment

                • Piet van Oostrum

                  #38
                  Re: Nested scopes, and augmented assignment

                  >>>>Antoon Pardon <apardon@forel. vub.ac.be(AP) wrote:
                  >API'm sorry to see you missed it, but since I had answered this already in
                  >APthis thread I saw at the moment no need to repeat it: There would be no
                  >APvalue for c, the line would raise an UnboundLocalErr or.
                  OK. That could have been chosen. But that would mean that instead of c.a =
                  b, where c is bound in a non-local scope, you have to write something like:

                  cc = c
                  cc.a = b

                  I don't find that useful.
                  --
                  Piet van Oostrum <piet@cs.uu.n l>
                  URL: http://www.cs.uu.nl/~piet [PGP 8DAE142BE17999C 4]
                  Private email: piet@vanoostrum .org

                  Comment

                  Working...