Finding the instance reference of an object

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Joe Strout

    #31
    Re: Finding the instance reference of an object

    On Oct 27, 2008, at 12:19 PM, gooberts@gmail. com wrote:
    I think this "uncontrive d" example addresses the C/Python difference
    fairly directly (both were tested):
    That's correct, but of course, C is a decades-old language barely a
    step above assembler. For a fair comparison, pick any modern OOP
    language, including the C derivatives (C++, Objective-C, Java), and
    compare a Python object to an object in that language, rather than to
    a struct.
    In Python, variables are just names/aliases for *references* to
    objects, not names for the objects/values themselves. The variable
    names themselves do not correspond directly to the objects' memory
    locations.
    Exactly! In C++, this would be like a pointer variable. In Java, RB,
    or .NET, it's like an object reference.
    While yes, technically, it is true that those reference
    values must be stored somewhere in memory, *that* is the
    implementation detail.
    Agreed. (And this was my point in response to someone arguing that no
    such location exists.)
    But is is not the *locations* of these
    references (i.e., the locations of the Python *variables*) that are
    copied around, it is the references themselves (the locations of the
    Python *objects*) that are copied.
    Right. The variables contain object references; these object
    references are copied (not referenced!) when you pass them into a
    function. That's call by value. In the case of an assignment, the
    reference is copied.
    >>All that exists in Python is a name->object mapping.
    >>
    >And what does that name->object mapping consist of? At some level,
    >there has to be a memory location that stores the reference to the
    >object, right?
    >
    I think this is answered above, but just to drive it home, in Python
    the memory locations of the variables themselves (an implementation
    detail), which hold the references to the objects, are inaccessible .
    Right. So too in Java, RB, .NET, etc. Pointers are nasty. But lack
    of pointers does not change the calling semantics.
    In C/C++, by contrast, variable names correspond directly to memory
    locations and objects, and you can easily find the addresses of
    variables.
    Hmm, no, the C++ equivalent of an object reference would be:

    SomeClass* foo;

    In fact, many C++ programmers prefer to typedef a pointer to each
    class, since it's the pointer (which is rough equivalent of a
    reference in newer languages) that you almost always want, rather than
    the class itself. So it would actually be:

    SomeClassPtr foo;

    Now, when you do:

    foo2 = foo;

    you are copying the object reference from foo to foo2, just as in
    Python. When you pass it into a function:

    void NiftyMethod(Som eClassPtr arg) {...}
    ...
    NiftyMethod(foo );

    You are copying the object reference right onto the call stack. This
    is pass by value, plain and simple. And because it is pass by value,
    you know that nothing NiftyMethod does can possibly change the value
    of foo -- that is, can make it point at something else. (It may well
    change the data that the object it points to contains, if SomeClass
    objects are mutable, but it can't change foo itself.) This is, again,
    just like Python and every other OOP language.

    Call by reference would be this:

    void NiftyMethod2(So meClassPtr &arg) {...}
    ...
    NiftyMethod2(fo o);

    Now, arg here is passed by reference (just like a ByRef parameter in
    RB or .NET). That means that NiftyMethod2 could very well change the
    value that is passed in. It could actually make foo point to
    something else.

    No Python method can do that, because Python arguments are ALWAYS
    passed by value. There is no call by reference in Python. Period,
    end of story, nothing to see here.

    Cheers,
    - Joe

    Comment

    • Terry Reedy

      #32
      Re: Finding the instance reference of an object

      gooberts@gmail. com wrote:
      On Oct 17, 5:39 pm, Joe Strout <j...@strout.ne twrote:
      >On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:
      >>No, it isn't. In many other languages (C, Pascal, etc.), a
      >>"variable" is commonly thought of as a fixed location in memory
      >>into which one can put values. Those values may be references
      >>to objects.
      In particular, memory is a linear sequence of writable cells. In Turing
      machines, they have no address, and access is by one-at-a-time movement.
      Subsequently, cells were given count addresses 0, 1, 2, ... .
      >Right, though not in languages like C and Pascal that don't HAVE the
      >notion of objects. We really ought to stop bringing up those
      >dinosaurs and instead compare Python to any modern OOP language.
      >>
      >> In Python, that's not how it works. There is no
      >>"location in memory" that corresponds to a variable with a
      >>particular name the way there is in C or Pascal or Fortran or
      >>many other languages.
      >No? Is there any way to prove that,
      The burden of proof is on those who claim a positive. Grant and I claim
      that there is no pink elephant in the room, and that we have looked
      around pretty thoroughly. You claim that there is. Show us what we missed.

      Anyway, suppose you read and execute "L123 = [1,2,3]". You can, I
      presume, perform any list method on that object. Where is it? Some
      memory theories say 'distributed, nowhere in particular'. Others say
      'concentrated, some particular neurons', but certainly nothing like the
      'where' of linear computer memory. Consider another object s = 'boo'.
      Which has the lower address?
      >without delving into the Python source itself?
      Python, the abstract information algorithm language, has no 'source',
      only a specification of syntax and semantics. The CPython source is the
      source for a particular computer machine implementation. Any such
      implemetation has to map abstractly locationless objects to particular
      blocks of computer memory without adding extraneous, Python-accessible
      semantics, such as relative position.
      >If not, then I think you're talking about an internal implementation
      >detail.
      I think *you* are. Giving Python objects an integer address is an
      (optional) implementation detail. Giving them a *fixed* integer address
      is an optional CPython detail that makes certain aspects of the code
      easier but which prevents re-locating garbage collection (which I
      believe Jython does).

      Anyone is free to view Python as only a linear-memory computer
      programming language (and, in some respects, as that, inferior to C).
      However, I have also viewed it as an algorithm language and, as a
      beginner (about 10 years ago), quickly dubbed it 'executable pseudocode'
      (and in that respect, much superior to C).

      Terry Jan Reedy

      Comment

      • Steven D'Aprano

        #33
        Re: Finding the instance reference of an object

        On Mon, 27 Oct 2008 13:11:04 -0600, Joe Strout wrote:
        On Oct 27, 2008, at 12:19 PM, gooberts@gmail. com wrote:
        >
        >I think this "uncontrive d" example addresses the C/Python difference
        >fairly directly (both were tested):
        >
        That's correct, but of course, C is a decades-old language barely a step
        above assembler.
        So what? It's not like C is no longer in common use.

        And even if C had disappeared off the landscape, there are millions of
        programmers, including beginning programmers, whose understanding of
        terms CBR and CBV are defined by the behaviour of languages like C and
        Pascal -- even if they haven't learned either language themselves.

        For a fair comparison, pick any modern OOP language,
        including the C derivatives (C++, Objective-C, Java), and compare a
        Python object to an object in that language, rather than to a struct.
        But we already know that many such languages use the exact same calling
        convention as Python, so all you would be showing is that languages with
        the same calling convention as Python have the same calling convention as
        Python.

        By common usage and technical definition, C is call by value. Argument
        passing in Python does not behave like C. So why insist that Python is
        also call by value?

        [snip]
        >While yes, technically, it is true that those reference values must be
        >stored somewhere in memory, *that* is the implementation detail.
        >
        Agreed. (And this was my point in response to someone arguing that no
        such location exists.)
        Obviously any computer which is based on the Von Newman architecture of
        CPU plus memory is going to store the reference *somewhere*. That's a
        detail unimportant at the Python level. But since clockwork or Conway's
        "Life" cellular automata are both Turing complete, it would be possible
        to build a Python implementation where the reference values weren't
        localised to a particular place in memory, but distributed over the
        system.

        >But is is not the *locations* of these references (i.e., the locations
        >of the Python *variables*) that are copied around, it is the references
        >themselves (the locations of the Python *objects*) that are copied.
        >
        Right. The variables contain object references; these object references
        are copied (not referenced!) when you pass them into a function. That's
        call by value. In the case of an assignment, the reference is copied.
        The value of a Python name is the Python object assigned to it, not an
        arbitrary memory location that points to the object. Even you would
        consider it obfuscatory if I executed this code:

        x = "Norwegian Blue"

        and then insisted that the value of x was "3086179808 L, but if I run that
        line of code again it could get another value, and naturally if you run
        it on your computer you're almost certain to get a different value".

        By your definition of "value=referenc e", the above is perfectly correct,
        and utterly, completely pointless, useless and unhelpful. It's rather
        like listing the ingredients of a cake as "Atoms". Technically true, but
        missing the point.



        [snip]
        You are copying the object reference right onto the call stack. This is
        pass by value, plain and simple.
        Who *cares* about copying the pointers? That's the WRONG LEVEL.
        Ultimately EVERY programming language that runs on a computer with memory
        is "Copy By Bit Flipping", but it would be useless and unhelpful to tell
        people that every programming language uses the exact same calling
        conventions: "bits are flipped, and that's the end of story".


        [snip]
        No Python method can do that, because Python arguments are ALWAYS passed
        by value. There is no call by reference in Python.
        Except that for millions of programmers who have learnt their terminology
        from Pascal and C, that implies that the values -- the data itself, not
        pointers to the data -- are copied. It implies that this can never fail:

        x = [1]
        y = function(x)
        assert x == [1]

        but of course it can fail, if function modifies x -- something which CBV
        implies can't happen.


        Period, end of story, nothing to see here.
        I think that this entire argument hinges on the poverty of your mental
        toolbox. You have a hammer (call by value) and a screwdriver (call by
        reference) and refuse to accept that there could possibly be any other
        calling model. Hence you force any actual calling model into the
        framework of CBV or CBR, no matter how much violence you have to do to
        simple terms like "value" to make it fit.


        --
        Steven

        Comment

        • Chuckk Hubbard

          #34
          Re: Finding the instance reference of an object

          I'm sorry to say I'm pretty confused by the example, but if you want
          something like

          bob = module.object()
          frank = module.object()
          and then to know that bob is bob from a list of instances, you could
          instead do something like:

          for person in listofnames:
          temp = module.object(p erson)
          list.append(tem p)

          where the __init__ function assigns the argument to object.nametag or
          something. This way you can retrieve the name from an index into the
          list, or retrieve the index by searching for the name...
          -Chuckk

          On Thu, Oct 16, 2008 at 5:04 PM, Astley Le Jasper
          <Astley.lejaspe r@gmail.comwrot e:
          On 16 Oct, 16:52, Carsten Haese <carsten.ha...@ gmail.comwrote:
          >Astley Le Jasper wrote:
          Sorry for the numpty question ...
          >>
          How do you find the reference name of an object?
          >>
          So if i have this
          >>
          bob = modulename.obje ctname()
          >>
          how do i find that the name is 'bob'
          >>
          >Why do you need to find that? You know that its name is 'bob'.
          >>
          >--
          >Carsten Haesehttp://informixdb.sour ceforge.net
          >
          I'm creating mulitple instances, putting them in a list, iterating
          through the list to send them to some functions where process them
          with some instance specific parameters. Something along the lines of:
          >
          bob = someobject()
          harry = someobject()
          fred = someobject()
          >
          parameterdict = {'bob':(0,1,2), 'harry':(3,4,5) ,'fred':(6,7,8) }
          people_list = (bob, harry, fred)
          >
          for person in people_list:
          add_parameters( person)
          >
          def add_parameters( person)
          mytuple = parameterdict[??????instance. name????]
          person.x = mytuple[0]
          person.y = mytuple[1]
          person.z = mytuple[2]
          >
          ... alternatively there is probably a very much easier way of doing
          it.
          --

          >


          --

          Comment

          • greg

            #35
            Re: Finding the instance reference of an object

            Steven D'Aprano wrote:
            By common usage and technical definition, C is call by value. Argument
            passing in Python does not behave like C. So why insist that Python is
            also call by value?
            Whether it behaves like C is not the test.

            Let's look at the definitions of the terms:

            (1) Call by value: The actual parameter is an expression. It is
            evaluated and the result is assigned to the formal parameter.
            Subsequent assignments to the formal parameter do not affect
            the actual parameter.

            (2) Call by reference: The actual parameter is an lvalue. The
            formal parameter becomes an alias for the actual parameter,
            so that assigning to the formal parameter has the same
            effect as assigning to the actual parameter.

            Seems to me that (1) describes exactly how parameter passing
            works in Python. So why insist that it's *not* call by value?

            --
            Greg

            Comment

            • Dale Roberts

              #36
              Re: Finding the instance reference of an object

              [I am actually enjoying this discussion, even though it does not address
              the OP's question. It is helping to solidify *my* understanding.]

              Joe Strout wrote:
              On Oct 27, 2008, at 12:19 PM, gooberts@gmail. com wrote:
              >
              >I think this "uncontrive d" example addresses the C/Python difference
              >fairly directly (both were tested):
              >
              That's correct, but of course, C is a decades-old language barely a step
              above assembler. For a fair comparison, pick any modern OOP language,
              including the C derivatives (C++, Objective-C, Java), and compare a
              Python object to an object in that language, rather than to a struct.
              Okay, sorry, should have had C++ from the start. See my spiffed-up
              example here, where I magically convert to C++ by replacing "struct"
              with "class" and adding the word "public:". Still behaves the same, though.

              I added the functions ByVal() and ByRef() to show that when you pass by
              value, the contents of the object cannot be changed. This is not
              possible in Python unless a copy of the object is made (which is what
              C++ does automatically for you in pass-by-value).

              In Python, the contents of the object are changed, which is most similar
              to the pass by reference (or by pointer) construct in C++. But, yes, as
              you say, technically:

              passing the object by reference
              == passing the address of the object by value.

              But I think that is, to most programmers, a surprising use of the term
              "pass by value".

              And note in my example, nowhere do I explicitly take the address of s1.
              The compiler does this for me in the ByRef() case. And nowhere to I make
              a copy of s1. Again, the compiler does this for me in the ByVal() case.
              The calls to ByVal() and ByRef() are identical. You cannot tell from the
              calls which thing is going to happen.

              -----------------------
              class MyClass {public: int a;} s1, s2;

              void ByVal(MyClass obj) {obj.a=42;}
              void ByRef(MyClass &obj) {obj.a=43;}

              int main()
              {
              s1.a = 1;
              s2 = s1;

              printf("s1.a %2d s2.a %2d\n", s1.a, s2.a);

              s1.a = 99;
              printf("s1.a %2d s2.a %2d\n", s1.a, s2.a);

              ByVal(s1);
              printf("s1.a %2d\n", s1.a);

              ByRef(s1);
              printf("s1.a %2d\n", s1.a);
              }
              --------------
              class mystruct:
              pass

              def ByObject(obj): obj.a=42

              s1 = mystruct()
              s1.a = 1
              s2 = s1

              print "s1.a %2d s2.a %2d" % (s1.a,s2.a)
              s1.a = 99
              print "s1.a %2d s2.a %2d" % (s1.a,s2.a)

              ByObject(s1)
              print "s1.a %2d" % (s1.a)

              --------------
              C++ OUTPUT
              s1.a 1 s2.a 1
              s1.a 99 s2.a 1 # note s2.a does not change when s1.a is modified
              s1.a 99 # contents of s1.a does not change when passed by val
              s1.a 43 # it does change when passed by ref

              Python OUTPUT
              s1.a 1 s2.a 1
              s1.a 99 s2.a 99 # s2.a "changes" because it's the same object as s1
              s1.a 42 # Contents of object does change with function call.

              ....and in Python, of course, as you say, what you call the "value" of
              s1, the address of the object, id(val), does not change.
              >>
              >[skipping lots of stuff we agree on!]
              >>
              >In C/C++, by contrast, variable names correspond directly to memory
              >locations and objects, and you can easily find the addresses of
              >variables.
              >
              Hmm, no, the C++ equivalent of an object reference would be:
              >
              SomeClass* foo;
              Whoah, nonsequitor there. Let's back up. I did not use the word
              "reference" , and that is the point. And I am correct that C variable
              names correspond to memory locations (or sometimes CPU registers -
              optimizers can really mangle things). And you can get the addresses of
              the variables themselves using the & operator.

              Have a look at my example code again. s1 and s2 ARE OBJECTS THEMSELVES,
              they are not references to objects. You can do this in C++ (not in
              Python). You can pass whole objects, by value (they are copied by the
              compiler), on the stack. And we both understand that you can't do that
              in Python. That is why we differentiate between "pass by reference" and
              "pass by value" in C++, and people generally understand what that means.
              ...
              void NiftyMethod2(So meClassPtr &arg) {...}
              ...
              NiftyMethod2(fo o);
              >
              Now, arg here is passed by reference (just like a ByRef parameter in RB
              or .NET). That means that NiftyMethod2 could very well change the value
              that is passed in. It could actually make foo point to something else.
              >
              No Python method can do that,
              Yes, absolutely agreed. A Python method can never change *which* object
              the caller points to, it can only change the *contents* of that object.

              But the same is true in C++ as well. In your example, the address of the
              foo variable itself can never be changed. You can change the *value* of
              foo (so it points to a different object), or you can change the contents
              of the object foo points to. foo is a variable with an address which you
              can usually see with a printf("%x", &foo), and that is different from
              the address of the object which you get when you say printf("%x", foo).

              The value &foo cannot be changed.
              because Python arguments are ALWAYS passed
              by value. There is no call by reference in Python. Period, end of
              story, nothing to see here.
              Yea, BUT... If you tell this to a C++ programer without any further
              explanation, they will be thoroughly confused and misinformed, unless
              you point them to this thread or amend that statement with your version
              of what "pass by value" means. I know what you mean, and you know what I
              mean, but that's because we've both read through this thread ;-)

              Look at my example. The ByVal() routine behaves how C++ programmers
              expect "pass by value" to work. The contents of the caller's object
              cannot be modified.

              So, then, what to tell a C++ programmer about how Python passes
              arguments? You say: tell them Python only passes by value. I disagree,
              because I think that would confuse them. Rather than try to map C++
              conventions onto Python, I think it is more useful to just tell them how
              it really works. Maybe a few statements like this:

              All values in Python are objects, from simple integers up to complex
              user-defined classes.

              An assignment in Python binds a variable name to an object. The
              internal "value" of the variable is the memory address of an object,
              and can be seen with id(var), but is rarely needed in practice.

              The "value" that gets passed in a Python function call is the address
              of an object (the id()).

              When making a function call, myfunc(var), the value of id(var) can
              never be changed by the function.

              Not sure if these are the best. To get into much more detail, you have
              to start explaining mutable and immutable objects and such.

              dale

              Cheers,
              - Joe

              Comment

              • Douglas Alan

                #37
                Re: Finding the instance reference of an object

                greg <greg@cosc.cant erbury.ac.nzwri tes:
                Seems to me that (1) describes exactly how parameter passing
                works in Python. So why insist that it's *not* call by value?
                Because there's an important distinction to be made, and the
                distinction has been written up in the Computer Science literature
                since Lisp first starting using the same argument passing semantics as
                Python back in 1958. The semantics are called "call by sharing".

                Many mainstream programming languages other than Python now use call
                by sharing. They include Java, JavaScript, Ruby, ActionScript, and C#.

                |>oug

                P.S. Lisp didn't call it "call by sharing" -- Lisp called it
                "binding". The designers of CLU invented the term "call by sharing"
                back in the 70s. (Or at least I believe they invented the term. They
                certainly did use the term.)

                Comment

                • Gabriel Genellina

                  #38
                  Re: Finding the instance reference of an object

                  En Tue, 28 Oct 2008 00:58:10 -0200, greg <greg@cosc.cant erbury.ac.nz>
                  escribió:
                  Steven D'Aprano wrote:
                  >
                  >By common usage and technical definition, C is call by value. Argument
                  >passing in Python does not behave like C. So why insist that Python is
                  >also call by value?
                  >
                  Whether it behaves like C is not the test.
                  >
                  Let's look at the definitions of the terms:
                  >
                  (1) Call by value: The actual parameter is an expression. It is
                  evaluated and the result is assigned to the formal parameter.
                  Subsequent assignments to the formal parameter do not affect
                  the actual parameter.
                  >
                  (2) Call by reference: The actual parameter is an lvalue. The
                  formal parameter becomes an alias for the actual parameter,
                  so that assigning to the formal parameter has the same
                  effect as assigning to the actual parameter.
                  >
                  Seems to me that (1) describes exactly how parameter passing
                  works in Python. So why insist that it's *not* call by value?
                  Those definitions are only applicable to unstructured, primitive types,
                  where the only relevant operations are "get value" and "assign value".
                  Structured types provide other operations too - like selection (attribute
                  get/set in Python). It is unspecified on both definitions above what
                  happens in those cases. Other posts in this same thread showed that Python
                  behaves similarly to call-by-reference in C++ with regard to data members
                  inside a structure (that is, mutable objects *can* be changed, and the
                  caller sees the change). Combined with your previous conclusion that
                  Python implements call-by-value, one should finally conclude that it can't
                  be neither cbv nor cbr - it's a different thing.
                  The term "call by object" was coined in the late '70s to describe this
                  behavior. More info about this ever-recurring topic can be found at


                  --
                  Gabriel Genellina

                  Comment

                  • Gabriel Genellina

                    #39
                    Re: Finding the instance reference of an object

                    En Tue, 28 Oct 2008 01:16:04 -0200, Dale Roberts <gooberts@gmail .com>
                    escribió:
                    So, then, what to tell a C++ programmer about how Python passes
                    arguments? You say: tell them Python only passes by value. I disagree,
                    because I think that would confuse them. Rather than try to map C++
                    conventions onto Python, I think it is more useful to just tell them how
                    it really works. Maybe a few statements like this:
                    >
                    All values in Python are objects, from simple integers up to complex
                    user-defined classes.
                    >
                    An assignment in Python binds a variable name to an object. The
                    internal "value" of the variable is the memory address of an object,
                    and can be seen with id(var), but is rarely needed in practice.
                    >
                    The "value" that gets passed in a Python function call is the address
                    of an object (the id()).
                    >
                    When making a function call, myfunc(var), the value of id(var) can
                    never be changed by the function.
                    >
                    Not sure if these are the best. To get into much more detail, you have
                    to start explaining mutable and immutable objects and such.
                    I don't think the above explanation is desirable, nor needed. Objects in
                    Python don't have an "address" - it's just a CPython implementation
                    detail. The fact that id() returns that address is just an implementation
                    detail too. The calling mechanism should be explained without refering to
                    those irrelevant details.

                    --
                    Gabriel Genellina

                    Comment

                    • Joe Strout

                      #40
                      Re: Finding the instance reference of an object

                      On Oct 27, 2008, at 11:28 PM, Gabriel Genellina wrote:
                      En Tue, 28 Oct 2008 00:58:10 -0200, greg
                      <greg@cosc.cant erbury.ac.nzesc ribió:
                      >
                      >Let's look at the definitions of the terms:
                      >>
                      >(1) Call by value: The actual parameter is an expression. It is
                      > evaluated and the result is assigned to the formal parameter.
                      > Subsequent assignments to the formal parameter do not affect
                      > the actual parameter.
                      >>
                      >(2) Call by reference: The actual parameter is an lvalue. The
                      > formal parameter becomes an alias for the actual parameter,
                      > so that assigning to the formal parameter has the same
                      > effect as assigning to the actual parameter.
                      >>
                      >Seems to me that (1) describes exactly how parameter passing
                      >works in Python. So why insist that it's *not* call by value?
                      Greg is right on the money here. It really is as simple as that.
                      Those definitions are only applicable to unstructured, primitive
                      types, where the only relevant operations are "get value" and
                      "assign value".
                      Nonsense. They apply to any type. See here for an introduction to
                      the topic in VB.NET:



                      The example shown uses an Integer, but guess what -- you can pass ANY
                      type either ByRef or ByVal, including object references (which are, of
                      course, quite common in VB.NET). The default is ByVal, which means
                      that (as in Python) the actual parameter is an expression, and no
                      assignments to it can affect the actual parameter. It DOES NOT MATTER
                      that both the formal parameter and the actual parameter may refer to
                      the same object, and if that object is mutable, you can mutate that
                      object.

                      But ByRef is another option, and if you pass an object reference
                      ByRef, then the formal parameter is an alias for the actual parameter,
                      and assignments to it change the actual parameter. Python doesn't
                      have this feature (nor much need for it, given its other features,
                      like tuple packing/unpacking). So, parameter passing in ByRef is
                      clearly exactly the same as the default "ByVal" parameter passing in
                      VB.NET... as well as Java, RB, C++ (when you remember that an object
                      reference in modern languages is like a pointer in C++), and every
                      other OOP language I've looked into.

                      Some of those languages, like Python, don't have different modes, and
                      so the language designers had no call to give their one mode a name.
                      So let's look at those that did have such a need, like VB.NET and
                      REALbasic. What's the default mode called? Why, it's "ByVal". Even
                      when that value is an object reference. This is short for "by value"
                      -- it's not short for "by sharing" or "by object" or any other such
                      silliness. No such terms are needed.

                      There are only the two cases, which Greg quite succinctly and
                      accurately described above. One is by value, the other is by
                      reference. Python quite clearly uses by value. Parameters are
                      expressions that are evaluated, and the resulting value copied into
                      the formal parameter, pure and simple. The continued attempts to
                      obfuscate this is pointless and wrong.

                      Best,
                      - Joe


                      Comment

                      • Dale Roberts

                        #41
                        Re: Finding the instance reference of an object

                        On Oct 28, 2:33 am, "Gabriel Genellina" <gagsl-...@yahoo.com.a r>
                        wrote:
                        En Tue, 28 Oct 2008 01:16:04 -0200, Dale Roberts <goobe...@gmail .com 
                        escribió:
                        >
                        >
                        >
                        So, then, what to tell a C++ programmer about how Python passes  
                        arguments? You say: tell them Python only passes by value. I disagree,  
                        because I think that would confuse them. Rather than try to map C++  
                        conventions onto Python, I think it is more useful to just tell them how  
                        it really works. Maybe a few statements like this:
                        >
                           All values in Python are objects, from simple integers up to complex
                           user-defined classes.
                        >
                           An assignment in Python binds a variable name to an object. The
                           internal "value" of the variable is the memory address of an object,
                           and can be seen with id(var), but is rarely needed in practice.
                        >
                           The "value" that gets passed in a Python function call is the address
                           of an object (the id()).
                        >
                           When making a function call, myfunc(var), the value of id(var) can
                           never be changed by the function.
                        >
                        Not sure if these are the best. To get into much more detail, you have  
                        to start explaining mutable and immutable objects and such.
                        >
                        I don't think the above explanation is desirable, nor needed. Objects in  
                        Python don't have an "address" - it's just a CPython implementation  
                        detail. The fact that id() returns that address is just an implementation 
                        detail too. The calling mechanism should be explained without refering to 
                        those irrelevant details.
                        >
                        --
                        Gabriel Genellina

                        I agree that it was a feeble and ill-advised attempt, and would like
                        to strike those lines from the record...

                        But the rest of the post is strong and accurate, I think, and coming
                        from a mainly C/C++ background, visualizing these object references
                        being passed around does help improve my understanding of Python's
                        *behavior* (and it apparently helps Joe too).

                        [May I refer to you as "Joe The Programmer" in my rhetoric? Are you a
                        "licensed" programmer making over $250K/year? ;-)]

                        If asked by a C++ programmer about Python's argument passing, I will
                        go with the Pass By Object explanation (which is why I called my
                        Python routine above ByObject()). Although there will be more
                        'splaining to do, at least it will give the C++ programmer pause, and
                        help them realize that there is something a little different that they
                        need to stop and try to understand.

                        If I just say "Python is Pass By Value, Period" without further
                        explanation, they will expect things to work as in my ByValue()
                        example above (where the caller's object contents cannot be changed),
                        and that is incorrect. And they may go and tell someone else, without
                        the detailed explanation, that "Dale says it's Pass By Value", and
                        I'll get blamed when their function surprisingly changes the contents
                        of the caller's object.

                        If I just say "Python is Pass By Reference", that is wrong too. As Joe
                        The Programmer points out, they will expect that the calling
                        *variable* itself can be changed, and that is wrong too.

                        They need to understand that Python does not map neatly, directly, and
                        completely to their C++ experience of Pass By Value (which involves
                        copying a variable), or Pass By Reference (which involves taking the
                        address of a variable).

                        The Key Concept in for a C++ programmer looking at Python is that,
                        unlike in C++, **Variables Cannot "Contain" Values**. All values in
                        Python are objects, and all variables in Python simply point to, or
                        are bound to, or refer to, these objects. The variables themselves do
                        not contain the objects - if you must (like Joe the Programmer), you
                        can say that all Python variables *contain* an object reference, and
                        it is these references that are passed around. Unlike C++, an object
                        reference is the ONLY thing that a Python variable can contain. A
                        function parameter is always passed as a reference to an object, not a
                        reference to a variable, or a copy of a variable or object.

                        And that is where the confusion arises. When people say ByRef or
                        ByVal, they usually mean by Reference to (address) or Value of (copy)
                        the *contents* of the passed variable. But, PYTHON VARIABLES DO NOT
                        "CONTAIN" VALUES (sorry for the shouting, but it is the most important
                        point here), so ByRef and ByVal lose their commonly accepted meanings.

                        In C++, ByValue requires a copy (and Python does not copy). In C++,
                        ByReference requires the address of a *variable* (an "lvalue"), and
                        variables do not have accessible addresses in Python.

                        ByObject, in contrast, requires neither (unless, like Joe The
                        Programmer, you consider the "value" of a variable to be the id(),
                        which is not what most people expect when they say "x=5" - they expect
                        the "value" to be 5). ByObject simply passes an object reference. Nice
                        and neat.

                        I think with that explanation (avoiding any mention of memory, or
                        object id's) will help them understand things better.

                        As you point out, this is a very old topic, but I guess each newcomer
                        to Python has to figure it out. The effbot's article you mention are
                        very helpful, and much of this thread is just a rehash of what he has
                        long ago spelled out very clearly.

                        But I am happy to add the strong C++ slant, since that is what I
                        understand best.

                        I like either "Call By Object", or "Call By Object Reference", the
                        latter of which is what Joe The Programmer seems to like, but insists,
                        confusingly, on rebinding it to the name "call by value".

                        dale

                        Comment

                        • Dale Roberts

                          #42
                          Re: Finding the instance reference of an object

                          On Oct 28, 11:59 am, Joe Strout <j...@strout.ne twrote:
                          ...
                          >
                          There are only the two cases, which Greg quite succinctly and  
                          accurately described above.  One is by value, the other is by  
                          reference.  Python quite clearly uses by value.  Parameters are  
                          expressions that are evaluated, and the resulting value copied into  
                          the formal parameter, pure and simple.  The continued attempts to  
                          obfuscate this is pointless and wrong.
                          >
                          Best,
                          - Joe
                          5 + 3

                          What is the "value" of that expression in Python? Can you tell me?

                          99.99% of programmers (who do not have this thread as context) will
                          say that the value is 8. But you say the value is the memory address
                          of the resulting object created when the + operator is applied to the
                          5 object and the 3 object. That is the "value" that is copied.

                          Okay, you can have it that way, but every time you explain to someone
                          that Python passes "By Value", you will have to add the additional
                          baggage that, oh, by the way, there is a completely different meaning
                          for "value" in Python than what you are used to.

                          Then the questions and puzzled looks will start...

                          And when they tell their friend that Joe The Programmer said it's Pass
                          By Value, your additional context may not be present any longer, and
                          the friend will be very confused.

                          In my opinion, best just to head it off and call it something
                          different so as not to confuse.

                          dale

                          Comment

                          • Aaron Brady

                            #43
                            Re: Finding the instance reference of an object

                            On Oct 27, 2:11 pm, Joe Strout <j...@strout.ne twrote:
                            On Oct 27, 2008, at 12:19 PM, goobe...@gmail. com wrote:
                            >
                            I think this "uncontrive d" example addresses the C/Python difference
                            fairly directly (both were tested):
                            >
                            That's correct, but of course, C is a decades-old language barely a  
                            step above assembler.  For a fair comparison, pick any modern OOP  
                            language, including the C derivatives (C++, Objective-C, Java), and  
                            compare a Python object to an object in that language, rather than to  
                            a struct.
                            >
                            In Python, variables are just names/aliases for *references* to
                            objects, not names for the objects/values themselves. The variable
                            names themselves do not correspond directly to the objects' memory
                            locations.
                            >
                            Exactly!  In C++, this would be like a pointer variable.  In Java, RB,  
                            or .NET, it's like an object reference.
                            >
                            While yes, technically, it is true that those reference
                            values must be stored somewhere in memory, *that* is the
                            implementation detail.
                            >
                            Agreed.  (And this was my point in response to someone arguing that no  
                            such location exists.)
                            >
                            But is is not the *locations* of these
                            references (i.e., the locations of the Python *variables*) that are
                            copied around, it is the references themselves (the locations of the
                            Python *objects*) that are copied.
                            >
                            Right.  The variables contain object references; these object  
                            references are copied (not referenced!) when you pass them into a  
                            function.  That's call by value.
                            snip.

                            What do you propose the name of the method of passing parameters
                            should be for the following function 'f' in C?

                            struct T {
                            int a;
                            int b;
                            int c;
                            };

                            void f( T t );

                            Given a 4-byte system word, how many bytes do you think are copied to
                            the stack upon calling 'f'?

                            Comment

                            • Steven D'Aprano

                              #44
                              Re: Finding the instance reference of an object

                              On Tue, 28 Oct 2008 09:59:57 -0600, Joe Strout wrote:
                              There are only the two cases, which Greg quite succinctly and accurately
                              described above. One is by value, the other is by reference. Python
                              quite clearly uses by value.
                              That is absolute nonsense, based on the idiotic assumption that
                              programmers should care more about an arbitrary reference to a value than
                              to the value itself.

                              I'm sure I've quoted the excellent effbot before, but he deserves
                              repeating:

                              [quote]
                              well, I guess you can, in theory, value an artificial number assigned
                              to an object as much as the object itself.

                              "Joe, I think our son might be lost in the woods"
                              "Don't worry, I have his social security number"
                              [end quote]

                              As I wrote yesterday:

                              The value of a Python name is the Python object assigned to it, not an
                              arbitrary memory location that points to the object. Even you would
                              consider it obfuscatory if I executed this code:

                              x = "Norwegian Blue"

                              and then insisted that the value of x was "3086179808 L, but if I run that
                              line of code again it could get another value, and naturally if you run
                              it on your computer you're almost certain to get a different value".

                              By your definition of "value=referenc e", the above is perfectly correct,
                              and utterly, completely pointless, useless and unhelpful. It's rather
                              like listing the ingredients of a cake as "Atoms". Technically true, but
                              missing the point.

                              Once we discard the unhelpful assumption that value=reference , your
                              entire argument falls apart.



                              --
                              Steven

                              Comment

                              • Antoon Pardon

                                #45
                                Re: Finding the instance reference of an object

                                On 2008-10-17, Joe Strout <joe@strout.net wrote:
                                >Python's assignment semantics (as opposed to its "object handling, a
                                >term for which I have no referent) are not the same as those of, say
                                >C.
                                >
                                They are, though. The only difference you've pointed out is that
                                *numbers* are different in Python vs. C, and that's an internal
                                implementation detail I was blissfully unaware of until this
                                discussion. (I'm grateful to know it, but it really doesn't matter in
                                day-to-day coding.)
                                No they are not. An assignment in Python is like making an (new) alias/reference,
                                while an asignment in C is copying the content of one variable into another.

                                --
                                Antoon Pardon

                                Comment

                                Working...