Finding the instance reference of an object

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steven D'Aprano

    #91
    Re: Finding the instance reference of an object

    On Sun, 02 Nov 2008 13:23:11 -0800, Aaron Brady wrote:
    But, doing so, an object is not the same as a reference to it, and all
    Python does is pass and copy references.
    No, that's what at least one particular implementation of Python does.
    That's not what Python does. The Python VM doesn't have any concept of
    "values" or "references " or "values which are actually references in
    disguise". The Python VM knows about *names in namespaces* and *objects*.



    --
    Steven

    Comment

    • Aaron Brady

      #92
      Re: Finding the instance reference of an object

      On Nov 2, 10:13 pm, Steven D'Aprano
      <ste...@REMOVE. THIS.cybersourc e.com.auwrote:
      On Sun, 02 Nov 2008 13:23:11 -0800, Aaron Brady wrote:
      But, doing so, an object is not the same as a reference to it, and all
      Python does is pass and copy references.
      >
      No, that's what at least one particular implementation of Python does.
      That's not what Python does. The Python VM doesn't have any concept of
      "values" or "references " or "values which are actually references in
      disguise". The Python VM knows about *names in namespaces* and *objects*.
      >
      --
      Steven
      I think we can conclude that Python passes by reference, since a
      function can modify objects that were passed in to it.

      Comment

      • Marc 'BlackJack' Rintsch

        #93
        Re: Finding the instance reference of an object

        On Mon, 03 Nov 2008 15:27:01 -0700, Joe Strout wrote:
        On Nov 3, 2008, at 2:36 PM, Aaron Brady wrote:
        >Python can do the swap operation on mutable types, for example.
        >
        That's in the "no fair" category. C can do a swap operation on mutable
        types, too, though it also has only pass-by-value. Same for Java, or
        for REALbasic or VB.NET using "ByVal" mode. The fact that you can
        mutate mutable types has absolutely nothing to do with whether the
        parameter was passed by reference or value. If was by reference, you
        can change it (the parameter itself, not something the parameter may
        refer to). If it's by value, you can't.
        >
        In Python, you can't. That's because parameters are passed by value.
        This conclusion is flawed because call-by-value is not the only parameter
        passing style with that characteristics .
        >By-Value and By-Reference are not the only passing methods. True or
        >False?
        >
        True, but the others are rarely used and don't apply to any of the
        languages we've been discussing.
        Maybe this is a surprise for you, because we haven't discussed this in
        much detail in this group lately, but it applies to Python which does
        call-by-object or call-by-sharing. ;-)

        Ciao,
        Marc 'BlackJack' Rintsch

        Comment

        • Steven D'Aprano

          #94
          Re: Finding the instance reference of an object

          On Mon, 03 Nov 2008 15:27:01 -0700, Joe Strout wrote:
          >By-Value and By-Reference are not the only passing methods. True or
          >False?
          >
          True, but the others are rarely used and don't apply to any of the
          languages we've been discussing.
          Yeah, uncommon, rare languages that nobody uses, like Java, Lisp and
          Python.




          --
          Steven

          Comment

          • Joe Strout

            #95
            Re: Finding the instance reference of an object

            On Nov 3, 2008, at 5:27 PM, Marc 'BlackJack' Rintsch wrote:
            Maybe this is a surprise for you, because we haven't discussed this in
            much detail in this group lately, but it applies to Python which does
            call-by-object or call-by-sharing. ;-)
            There's no such thing. Those are just terms made up by the Python
            community to in place of the more standard "call-by-value" terminology
            to make Python seem more mysterious than it really is. I guess you
            can call it "purple bananas" if you want, but the behavior is exactly
            the same as what every other language calls call-by-value.

            But I really am trying not to continue this debate. So that's my last
            reply about it for tonight, I promise. :)

            Cheers,
            - Joe
            <http://www.strout.net/info/coding/valref/>


            Comment

            • Aaron Brady

              #96
              Re: Finding the instance reference of an object

              On Nov 3, 8:33 pm, Joe Strout <j...@strout.ne twrote:
              On Nov 3, 2008, at 5:27 PM, Marc 'BlackJack' Rintsch wrote:
              >
              Maybe this is a surprise for you, because we haven't discussed this in
              much detail in this group lately, but it applies to Python which does
              call-by-object or call-by-sharing.  ;-)
              >
              There's no such thing.  Those are just terms made up by the Python  
              community to in place of the more standard "call-by-value" terminology  
              to make Python seem more mysterious than it really is.  I guess you  
              can call it "purple bananas" if you want, but the behavior is exactly  
              the same as what every other language calls call-by-value.
              >
              But I really am trying not to continue this debate.  So that's my last  
              reply about it for tonight, I promise.  :)
              >
              Cheers,
              - Joe
              <http://www.strout.net/info/coding/valref/>
              Here is the link to Barbara Liskov's paper, 1992, linked on
              effbot.org.

              "...argumen ts are passed "by object"; the (pointer to the) object
              resulting
              from evaluating the actual argument expression is assigned to the
              formal."



              However a Google search for "call by object", in quotes, returns
              mostly Python-related links, which I find somewhat suspicious.

              The search for call by sharing was more successful:

              " Call by Sharing
              The caller and called routine communicate only through the argument
              and result objects; routines do not have access to any variables of
              the caller.... if a routine assigns an object to a formal argument
              variable, there is no effect on the caller."



              That's an accurate description of Python. If VB.NET does the same
              thing, I'll just assume that the designers named their keyword "ByVal"
              instead of "ByShare", either to accommodate immutable primitives
              (numbers), or to keep the keyword short.

              Comment

              • Hendrik van Rooyen

                #97
                Re: Finding the instance reference of an object

                "Aaron Brady" <castironpi@gma il.comwrote:
                >I think we can conclude that Python passes by reference, since a
                >function can modify objects that were passed in to it.
                Sort of - if the modification is by "side effect" - so you
                can append to a list, for instance.

                However, if you use the passed param name on the left
                of an assignment statement, you get a new local object.
                I think it is this that lies at the root of the confusion.

                - Hendrik



                Comment

                • Steven D'Aprano

                  #98
                  Re: Finding the instance reference of an object

                  On Mon, 03 Nov 2008 19:33:52 -0700, Joe Strout wrote:
                  On Nov 3, 2008, at 5:27 PM, Marc 'BlackJack' Rintsch wrote:
                  >
                  >Maybe this is a surprise for you, because we haven't discussed this in
                  >much detail in this group lately, but it applies to Python which does
                  >call-by-object or call-by-sharing. ;-)
                  >
                  There's no such thing. Those are just terms made up by the Python
                  community to in place of the more standard "call-by-value" terminology
                  to make Python seem more mysterious than it really is.
                  I call bullshit on you. We've already shown you that the term call-by-
                  sharing (a.k.a. call-by-object or call-by-object-sharing) goes back to
                  the 1970s and such computer scientists as Barbara Liskov. The language
                  CLU used the term back in 1974, and it is possible that CLU wasn't the
                  first language to use it. That's over fifteen years before the first
                  release of Python.

                  This is not the first time it's been pointed out to you. And it won't be
                  the last. And I predict that it will make no difference to you at all:
                  you will still continue to pretend that Liskov et al aren't even worth
                  acknowledging, and you will continue to make the asinine definition that
                  the "value" of x following "x = 1" is 0x97b3250 rather than 1.


                  I guess you can
                  call it "purple bananas" if you want, but the behavior is exactly the
                  same as what every other language calls call-by-value.
                  Again, I call bullshit. Python's behaviour is not the same as what
                  Pascal, or C, calls call-by-value. It is what many Java people call "call-
                  by-value", because they make the same idiotic definition that the value
                  of a variable is some arbitrary and hidden reference to the thing of
                  interest:

                  "Java is call-by-value, where value means a reference to the actual
                  value, except for primitives, where the value is the actual value."

                  It is an idiotic definition, the sort of thing that only a very smart
                  person can make, twisting the plain and intuitive meaning of value ("what
                  is denoted by a symbol") just to avoid having to accept that there are
                  more things in reality than their pet theory includes.

                  It's not we Python folk who are guilty of misusing terminology, it is you
                  and your fellow VB and Java folk who are misusing the term call-by-value
                  to describe something which is nothing like call-by-value in Pascal and
                  C. There is a simple test you can do: pass a value to a function, and
                  have the function mutate that value. If the mutation appears in the
                  caller's environment, then the value wasn't copied and it is not call-by-
                  value. In Python:

                  def mutate(alist):
                  alist.append(1)

                  L = [1, 2]
                  mutate(L) # supposedly call by value
                  assert L == [1, 2]

                  If the assert statement fails (and it does), then no copy was made and
                  Python is not call-by-value.

                  So Python is not call-by-value, and it's not call-by-reference, so ...
                  either Python doesn't exist, or it uses a different calling convention.


                  --
                  Steven

                  Comment

                  • Craig Allen

                    #99
                    Re: Finding the instance reference of an object

                    >
                    If the assert statement fails (and it does), then no copy was made and
                    Python is not call-by-value.
                    >
                    So Python is not call-by-value, and it's not call-by-reference, so ...
                    either Python doesn't exist, or it uses a different calling convention.
                    >
                    coming from C/C++ Python seemed to me call by reference, for the
                    pragmatic reason you said, modificaitons to function arguments do
                    affect the variable in the caller. The confusing part of this then
                    comes when immutable objects are passed in. You still get a reference,
                    but rather than complaining if you change the value of that parameter
                    at might happen if immutible was "const" and the code was const-
                    correct. Honestly I understand how this can change the callBy paradigm
                    I don't see it that way (though I've duly remembers call-by-sharing
                    and call-by-object) for communication purposes). I see it as a factor
                    of the way variable names are rebound, that is, the "quirk" I remember
                    is not about how entities are passed to functions, but the quirk of
                    how python deals with modifications to "immutibles ".

                    That is, python lets you change object references pointing to
                    immutibles, which looks like changing the value referenced, by
                    rebinding.

                    So is that objectionable?

                    Comment

                    • Mel

                      Re: Finding the instance reference of an object

                      Craig Allen wrote:
                      That is, python lets you change object references pointing to
                      immutibles, which looks like changing the value referenced, by
                      rebinding.
                      >
                      So is that objectionable?
                      OK once in a while, but it wouldn't do for everyday.

                      Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52)
                      [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
                      Type "help", "copyright" , "credits" or "license" for more information.
                      # Case A:
                      >>a=2
                      >>b=3
                      >>a+b
                      5
                      # Case B:
                      >>id(a)
                      135720748
                      >>id(b)
                      135720736
                      >>id(a+b)
                      135720712
                      >>id(a)+id(b)
                      271441484

                      In talking about Python programs, we'd really like to talk like case A.
                      Meaningful values are tagged with names, passed around, operated on. We
                      get our result and leave. Case B adds a level of indirection that, if we
                      mention it, just obscures our actual task of summing two numbers.

                      Consider the fragment

                      def f (x, y):
                      return x+y
                      a=2
                      b=3
                      c = f(a, b)

                      We can imagine a cross-namespace assignment operator (which we could write
                      =\= if we needed more weird glyphs.) It works exactly like ordinary
                      assignment except that the LHS is evaluated in a different namespace from
                      the RHS. We could use our new operator to trace the execution of this code
                      fragment. The core of it would be

                      x =\= a # outer to inner assignment
                      y =\= b
                      c =/= x+y # inner to outer assignment

                      It's ordinary assignment all the way, except for being from an outer to an
                      inner, or from an inner to an outer namespace. Note how changing to
                      mutable arguments makes no difference (literal arguments this time):

                      c = f ([2], [3])

                      x =\= [2]
                      y =\= [3]
                      c =/= x+y

                      Replacing =\= and =/= with = loses us our cross-namespace conceit, but the
                      code still runs and does what Python code does.

                      So why import the wrong terminology from some other field, then try to save
                      it by mangling the definition of 'value' so that it's no use in discussing
                      what a program is supposed to do?

                      ob: Python, I refer you to the _Beyond the Fringe_ sketch "Portrait from
                      Memory", a reminiscence by a pseudo Bertrand Russell ("Moore, have you some
                      apples in that basket?".) You want to have to talk like this all the time?
                      See what I mean?

                      Comment

                      • Joe Strout

                        Re: Finding the instance reference of an object

                        On Nov 4, 2008, at 7:42 AM, Craig Allen wrote:
                        coming from C/C++ Python seemed to me call by reference, for the
                        pragmatic reason you said, modificaitons to function arguments do
                        affect the variable in the caller. The confusing part of this then
                        comes when immutable objects are passed in.
                        Yes, you stepped in the wrong direction right away and led yourself
                        into a morass of contradictions.

                        The correct way to look at it is that a Python reference is like a C++
                        pointer. C++ pointers are passed by value (unless you add & to
                        explicitly make a parameter by-reference), yet you can still use them
                        to mutate the objects they point to, right? Same thing in Python.
                        Nothing at all mysterious going on here. Compare this:

                        typedef Spam* SpamPtr; // (where Spam is some class)
                        // ...
                        void foo(SpamPtr spam)
                        {
                        spam->count = 4;
                        }

                        When you call foo, it modifies the spam object passed in, even though
                        the parameter is by-value. How? Because (looking more carefully),
                        you didn't actually pass in a Spam object; you passed in a POINTER TO
                        a Spam object. That pointer remained unchanged. You just used the
                        pointer to change some other data living on the heap. This is the
                        case exactly equivalent to Python:

                        def foo(spam):
                        spam.count = 4;

                        Same thing here; the variable you pass in is a reference to a Spam
                        object, and while that reference remains unchanged by the call, it is
                        used to change some other data that lives on the heap.

                        Here's a C++ example that has no analog in Python, because it uses
                        call-by-reference:

                        void throwOut(SpamPt r &spam)
                        {
                        printf("throwin g out %s\n", spam->brand);
                        delete spam;
                        spam = nil;
                        }

                        Now here, when you invoke throwOut on a SpamPtr, your own SpamPtr
                        variable (the one that you pass in) actually gets set to nil. That's
                        because the formal parameter here is just an alias of the actual
                        parameter. You can't do that in Python; this attempt:

                        def throwOut(spam):
                        print "throwing out %s\n", spam.brand
                        spam = nil

                        would entirely fail to have any effect whatsoever on the Spam
                        reference you pass in. "spam" here is just a local variable within
                        the throwOut function, which has no connection to the variable passed
                        in other than it gets a copy of its value (i.e., it initially refers
                        to the same object as the actual parameter). This doesn't work, and
                        the C++ throwOut function has no analog in Python, because Python has
                        no call-by-reference.

                        Here's another C++ example that has no analog in Python, because it
                        passes an object directly on the stack rather than a reference to it:

                        void bar(Spam spam)
                        {
                        spam.count = 5;
                        }

                        This is the one that I know particularly confuses some users, because
                        it LOOKS like what you could do in Python, and has the same behavior
                        on the surface. But it's not analogous at all, because the "spam"
                        local variable here (and presumably the one in the calling context) is
                        an object stored directly on the stack, rather than a reference to an
                        object on the heap. Python can't do that (nor can Java, nor
                        REALbasic, etc.). This example is also call-by-value, but the value
                        in this case is a type that has no analog in Python. Python object
                        variables are references to objects on the heap, just like pointers in
                        C++ to objects created with "new". So this example is a red herring.

                        I'd be very interested in hearing whether, as a C/C++ user, the above
                        explanation is clear and makes sense to you.

                        Thanks,
                        - Joe


                        Comment

                        • Bruno Desthuilliers

                          Re: Finding the instance reference of an object

                          Joe Strout a écrit :
                          On Nov 3, 2008, at 5:27 PM, Marc 'BlackJack' Rintsch wrote:
                          >
                          >Maybe this is a surprise for you, because we haven't discussed this in
                          >much detail in this group lately, but it applies to Python which does
                          >call-by-object or call-by-sharing. ;-)
                          >
                          There's no such thing. Those are just terms made up by the Python
                          community
                          Did you read *any* of the many answers in this thread ? This term comes
                          from lisp, and existed years before Python.
                          to in place of the more standard "call-by-value" terminology
                          to make Python seem more mysterious than it really is.
                          Looks a bit paranoid to me.

                          Comment

                          • Steven D'Aprano

                            Re: Finding the instance reference of an object

                            On Tue, 04 Nov 2008 09:06:45 -0700, Joe Strout wrote:
                            This example is also call-by-value, but the value in this case is a type
                            that has no analog in Python.
                            I'm disappointed to see that my prediction that Joe would, yet again,
                            utterly ignore all the arguments against his pet theory was correct. It's
                            gratifying to be proven right, of course, but I'd prefer to be wrong and
                            reduce the amount of confusion and obfuscation that Joe is causing.

                            Over the years, I've had the misfortune to deal with many people like
                            Joe. They get a fixed idea in their head, and regardless of the facts
                            they will stick to it, no matter what: "when the facts disprove your pet
                            theory, ignore the facts".

                            When we're talking about the value of a variable in Python, why on earth
                            would you drag entities that do not exist in Python into the discussion?
                            That is too low a level. It's analogous to my earlier tongue-in-cheek
                            suggestion that all languages are in fact call-by-bit-flipping:
                            technically true at some level of explanation, but not at the level of
                            the Python virtual machine.



                            --
                            Steven

                            Comment

                            • Joe Strout

                              Re: Finding the instance reference of an object

                              On Nov 4, 2008, at 3:42 PM, Steven D'Aprano wrote:
                              >This example is also call-by-value, but the value in this case is a
                              >type
                              >that has no analog in Python.
                              >
                              I'm disappointed to see that my prediction that Joe would, yet again,
                              utterly ignore all the arguments against his pet theory was correct.
                              I'm not doing that, but the folks on the other side are. (Well, I
                              don't know if you are in particular, as I've been deleting your
                              messages to save my blood pressure... this one caught my eye though,
                              alas.)

                              For example: we have arguments that you can "modify" a parameter
                              passed to a function in Python. These ignore the fact that you can
                              only use (dereference) that parameter to modify something else, no
                              different from a pointer passed by-value in C/C++. And, when a very
                              simple test for by-reference is brought up (i.e. writing a Swap
                              method), this gets ignored again and again, by the otherwise perfectly
                              nice fellow I've been discussing this with privately for days. There
                              are many other examples.

                              It boils down to this: Python's behavior is demonstrably the same as
                              any other modern OOP language, INCLUDING those that have both by-
                              reference and by-value parameter modes, except that in Python (as well
                              as Java), only the by-value mode is available.

                              This is easily shown, and I've done exactly that at <http://www.strout.net/info/coding/valref/
                              >.
                              But I predict that you'll ignore all this evidence that goes against
                              your pet theory, and continue to cause confusion and obfuscation on
                              the topic.
                              When we're talking about the value of a variable in Python, why on
                              earth
                              would you drag entities that do not exist in Python into the
                              discussion?
                              I don't, but others do, for example bringing up C structs or C++
                              objects on the stack, which don't exist in Python (Python objects live
                              on the heap, and all you have on the stack are references to them; the
                              proper C/C++ analogy is an object created with "new" and referenced
                              entirely via pointers).
                              That is too low a level. It's analogous to my earlier tongue-in-cheek
                              suggestion that all languages are in fact call-by-bit-flipping:
                              technically true at some level of explanation, but not at the level of
                              the Python virtual machine.
                              I agree that we don't need to talk about bits. But we do need to
                              understand whether code such as:

                              a = SomeClass()
                              b = a

                              creates two objects, or merely two references to the same object.
                              Once we know whether we're dealing with values or references, then
                              everything else becomes simple and clear, no matter what language
                              we're building in.

                              I know you really want Python to be unique and special -- and it is,
                              in many ways, but this isn't one of them. Python is an OOP language
                              whose variables contain references to objects, and where such
                              references are passed (by value) to methods, just like Java, and like
                              the default parameter mode in VB.NET, REALbasic, and C++ (though those
                              languages also offer a by-reference mode that Python and Java do not).

                              Your continued attempts to obfuscate this simple behavior does no
                              credit to you or Python.

                              Best,
                              - Joe

                              Comment

                              • Joe Strout

                                Re: Finding the instance reference of an object

                                On Nov 4, 2008, at 3:54 PM, Steven D'Aprano wrote:
                                At the level of Python code, Python operates on *objects*. When you
                                call
                                a function with an argument, the argument (an object) is NOT copied,
                                it
                                is passed to the function. If you mutate the argument inside the
                                function, you are changing the object and the caller will see the
                                mutation: this is just like call-by-reference, and unlike call-by-
                                value.
                                And here is the key bit that you are missing.

                                When you pass a reference to an object to a function, and then mutate
                                the object, then OF COURSE the caller (as well as any other holders of
                                a reference to that object) will see the mutation. This is true in
                                ANY language. Pick your language, and I will demonstrate it. Here
                                are a few to get us started (assume a class "Person" with an attribute
                                "zipcode"):

                                C++:
                                void foo(PersonPtr who) {
                                who->zipcode = 12345;
                                }

                                Java:
                                void foo(Person who) {
                                who.zipcode = 12345;
                                }

                                REALbasic/VB.Net:
                                Sub foo(ByVal who as Person)
                                who.zipcode = 12345
                                End Sub

                                Python:
                                def foo(who):
                                who.zipcode = 12345


                                So please clarify your position by identifying which statement applies:

                                1. You don't believe that these languages are actually passing by value.
                                2. You don't believe these examples are mutating an object.
                                3. You don't believe these mutations can be seen by the caller after
                                the call.
                                4. You now see how a mutating an object within a function tells you
                                NOTHING about how the reference to that object was passed.
                                5. You see that the first three languages above are passing a
                                reference by value and using that to mutate and object, yet for
                                reasons still mysterious, the Python example (which has exactly the
                                same behavior) must be doing something different.

                                I hate being confrontational , but you're the one accusing me of
                                ignoring evidence against my "pet theory" (by which you mean the
                                standard definitions of c-b-v and c-b-r). Let's see what you do with
                                this evidence that directly contradicts yours.

                                Sigh.
                                But if you assign a different object to the argument name, the caller
                                does NOT see the change, which is just like call-by-value.
                                This at least you have correct.
                                So depending
                                on what type of object the argument is, and depending on what you do
                                inside the function, you get something that looks rather like call-by-
                                value or call-by-reference semantics.
                                But no, you don't, as I just demonstrated above (and explained a week
                                ago at <http://www.strout.net/info/coding/valref/>). You always have
                                call-by-value semantics. The semantics are exactly the same as in any
                                other language with anything resembling an object reference, including
                                those with both "ByVal" and "ByRef" modes (except that there is no
                                equivalent to the "ByRef" mode in Python).
                                But what the Python VM does is the
                                same no matter what you do: Python's calling model is different from
                                either byval or byref.
                                No, it's exactly byval. No. Different. In. Any. Way.

                                Let's tackle it this way: one of the following must be true for your
                                belief system to prop itself up at all:

                                1. Python's behavior is different from Java, REALbasic, VB.NET, and C++.
                                ....or...
                                2. None of those languages mentioned use call-by-value.

                                In fact both of these statements are false, but we can cut our time
                                and effort in half if you will just select the one that you believe to
                                be true, so we can focus on that. Which is it?

                                Thanks,
                                - Joe

                                Comment

                                Working...